1 Objectives

This notebook aims at

2 Life tables data (ETL)

Life data tables are downloaded from https://www.mortality.org.

See also https://www.lifetable.de.

We investigate life tables describing countries from Western Europe (France, Great Britain –actually England and Wales–, Italy, the Netherlands, Spain, and Sweden) and the United States.

We load the one-year lifetables for female, male and whole population for the different countries.

2.1 Retypage

We begin by retyping the columns. The schema of df, our universal table, is the following :

Column Name Column Type
Year integer
Age integer
mx double
qx double
ax double
lx integer
dx integer
Lx integer
Tx integer
ex double
Country factor
Gender factor

In order to avoid coercion problems and NA warnings, the column Age : 110+, is processed as Age : 110.

2.2 Western countries in 1948

Here we plot the central death rates of all Countries at all ages for the year 1948.

plot

Spain and Italy have higher death rates than the other countries from 0 to 30-45.

We can see that the lower central death rates are between 1 and 15 years old. Between 15 and 30 years old, this rate seems to increase a bit, and past 30 years old, the graph follows a linear function, meaning that the probability of dying past 30 years old become almost proportional to the age.

We also notice that the women have lower death rates than men.

We can see that between 0 and 45 years old France, Spain and Italy have higher central death rates than USA, while the others countries have similar or lower death rates. Infant mortality peaks is 5 times more important in Italy and Spain than in the US. However, in Sweden and Netherlands the death_rates are lower than in the US, especially for men between 30 and 60 years old, the mortality is almost half of the american one. Between 45 and 75 years old european countries have lower death rates than america. Past 75 years old, the disparities sooth, except maybe for Spanish women who have a minor mortality.

2.3 Death rates evolution since WWII

Now we will take a look at the evolution of death rates after the second world war. We plot the central death rates as a function of Age for the years 1946, 1956, 1966, … , 2016.

We can see that the mortality quotients have decreased decade by decade, especially at birth, and are generally at their lowest for the year 2016. We observe the same phenomenon during all these years than in 1948, the central death rates are low from 1 to 15, then increase and reach a peak around 25 years old, and finally seems to increase proportionaly from 30 years old. We also see that women have lower death rates than men, for all countries.

The peak around 25 years old is really noticeable for the men in all countries, while for women it isn’t as visible. This may be cause by suicide, because while women have an higher attempted suicide risks, men tend to employ more radical methods to kill themselfs. In 2008 the male-female rate ratio of suicide in Europe was 4.0 and in the USA 3.6, according to Suicide in the World, by Peeter Värnik. An other factor might be the higher propotion of men dying in motor vehicle crashes, for example in 2018 71% of motor vehicule deaths were men in the US. Men tend to have more high risks driving practices than women, in 2008 40% of males drivers killed on the road had BACs ≥ 0.08 percent, against 20% for females. All of these number come from this analysis of data from the U.S. Department of Transportation’s Fatality Analysis Reporting System (FARS).

This spike appears in 1956 and 1966, making the male’s curve diverge from the women one, but tend to flatten in 2006 and 2016 except in the US.

We observe that the mortality quotients for USA are higher than the european ones.

Here the function ratio_mortality_rateswith signaturefunction(df, reference_year=1946, target_years=seq(1946, 2016, 10))` that takes as input :

  • a dataframe with the same schema as life_table,
  • a reference year ref_year and
  • a sequence of years target_years

and that returns a dataframe with schema:

Column Name Column Type
Year integer
Age integer
mx double
mx.ref_year double
Country factor
Gender factor

where (Country, Year, Age, Gender) serves as a primary key, mx denotes the central death rate at Age for Year and Gender in Country whereas mx_ref_year denotes central death rate at Age for argument reference_year in Country for Gender.

We now draw plots displaying the ratio \(m_{x,t}/m_{x, 1946}\) for ages \(x \in 1, \ldots, 90\) and year \(t\) for \(t \in 1956, \ldots, 2016\) where \(m_{x,t}\) is the central death rate at age \(x\) during year \(t\).

We observe that the central death rates has decreased for every country and every age since 1946. The infant mortality, between 0 and 15 years old, in 2016 is 10 times lower than in 1946 in European countries. It appears that the mortality of the women has decreased the most since 1946.

In the US this drop is less drastic, and we can notice that around 30 for males for 2006 and 2016, the ratio doesn’t follow the overall diminuition unlike in the previous decade. There is a similar phenomenon for females, but less important.

4 Rearrangement

Now we compute a new dataframe df_pivot, with primary key (Gender,Year,Country), with a column for each Age from 0 to 110.

According to https://www.lifeexpectancy.org/lifetable.shtml, life expanctancy \(e(x)\) of persons alive at age \(x\) is computed with the following method :

\[ e(x) = \frac {T(x)} {l(x)} \] where

\[ l(x + 1) = l(x) \cdot e^{-m(x)} \] So we have \[ l(x + 2) = l(x + 1) \cdot e^{-m(x + 1)} = l(x) \cdot e^{-m(x)} \cdot e^{-m(x + 1)} = l(x) \cdot e^{-(m(x) + m(x + 1))} \] Therefore, \(\forall n \in [|1, 110 - x|]\):

\[ l(x + n) = l(x) \cdot e^{-\sum_{i = 0}^{n - 1} m(x + i)} \] And for \(T(x)\): \[ T(x) = \sum_{n = 0}^{110 - x} L(x + n)\\ L(x) = \frac 1 2 (l(x) + l(x + 1)) = \frac 1 2 l(x) (1 + e^{-m(x)}) \] So \(\forall n \in [|1, 110 - x|]\) \[ L(x + n) = \frac 1 2 l(x + n) (1 + e^{-m(x + n)})\\ = \frac 1 2 l(x) \cdot e^{-\sum_{i = 0}^{n - 1} m(x + i)} (1 + e^{-m(x + n)}) \] Which gives us: \[ T(x) = \sum_{n = 0}^{110 - x} L(x + n) = \frac 1 2 l(x) (1 + e^{-m(x)}) + \sum_{n = 1}^{110 - x} \frac 1 2 l(x) \cdot e^{-\sum_{i = 0}^{n - 1} m(x + i)} (1 + e^{-m(x + n)})\\ = \frac 1 2 l(x) \cdot [(1 + e^{-m(x)}) + \sum_{n = 1}^{110 - x} e^{-\sum_{i = 0}^{n - 1} m(x + i)} \cdot (1 + e^{-m(x + n)})] \] This way:

\[ e(x) = \frac {T(x)} {l(x)} = \frac 1 2 \cdot [(1 + e^{-m(x)}) + \sum_{n = 1}^{110 - x} e^{-\sum_{i = 0}^{n - 1} m(x + i)} \cdot (1 + e^{-m(x + n)})] \]

- [ ] Using life_table_pivot compute life expectancy at birth for each Country, Gender and Year

#Life expectancy

life_expectancy is a function that takes as input a vector of mortality quotients, as well as an age, and returns the residual life expectancy corresponding to the vector and the given age.

Then we have life_expectancy_all, a function that takes as input a dataframe with the same schema as life_table and returns a data frame with columns Country, Gender, Year, Age defining a primary key and a column res_lex containing residual life expectancy corresponding to the pimary key.

We plot the life expectancy at birth for each country, gender and year.

Here we can see that the the life expanctancy at birth has increased a lot the past 150 years. There are two low peaks during the two world wars for european countries, especially for men. Females have higher life expectancy than males in each country.

We observe that the residual life expectancy is increasing as the time goes, and this rise is going faster since circa 1975. We also notice that the residual life expectancy of women is higher than the men’s one for each country. The US is once again a little bellow european countries, with the lowest life expectancy for both men and women. In Netherlands we observe a little decreasing in the residual life expectancy between 1950 and 1970 before increasing again.

5 PCA

On the screeplot we can see that the 3 first component have an eigenvalue >1 and explains almost 98% of variance, therefore we can reduce dimension from 114 to 3 without major loss of information. In fact the first component alone represent more than 89.7 % of the variance, so it could be a good unique index, but we will use Kaiser’s rule.

On the correlation circle we can see that all the variables are being well represented, and on the biplot that there are 3 main groups for both sex.

6 CCA

We build a function design that takes as input + a dataframe like life_table_pivot, + a couple of countries, say Spain and Sweeden, + a vector of Year, say 1948:1998 + a Gender say Female returns a matrix called \(Z\) with rows corresponding to Year and columns corresponding to couples (Country, Age).

We see that the chi-square statistic is high, which means that there is a strong link between the year and the couples (Country, Age). 91.956 % of the variation is explained by the first two dimensions, which is acceptable.

On the first plot we distinguish 3 groups of year, from 1948 to early 1960, the end of 1980 to 1999, and the group formed by the years in between.

On the second plot, we see that age 0 to 4 are really well represented. Then we have 3 main groups of age : 0 to 43, 44 to 96 and 97 to 110 who are completely negatively correlated.

7 Lee Carter

Pour faire une modélisation Lee-Carter il suffit de jouer avec les paramêtres de la fonction suivante:

`lee_carter <- function(df, a.country="France", a.year=1933:1995, a.gender = "Both")`

Pour afficher un graph du fit:

`lee_carter.fit <- function(df, leca, years = NULL)`

Forecast des \(k_t\), walks le nombre d’année de prédiction:

`leca.forecast <- lee_carter.forecast <- function(leca, walks = 50)`

Pour la life expectancy à partir d’un forecast:

`leca.expectancy <- function(leca.forecast)`

Pour comparer avec les valeurs réelles, voir le dernier graphe.

7.1 US

7.2 Europe

8 References

Life tables and demography

Graphics and reporting

Tidyverse

PCA, SVD, CCA

LS0tCnRpdGxlOiAnSG9tZXdvcmsgSUk6IFNWRCBhbmFseXNpcyAmIExpZmUgVGFibGVzJwphdXRob3I6ICJCZXRlbmQgTWFyaWUgYW5kIERlc21hcmV0eiBGw6lsaXgiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IG5vbmUKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBrZWVwX21kOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2M6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIHRvYzogeWVzCnBhcmFtczoKICBjb3VudHJ5OiBGcmFuY2UKICBjb3VudHJ5X2NvZGU6IGZyX3QKICBkaXJwYXRoOiBMSUZFX1RBQkxFUy8KICB0aW1lY291cnNlOiAxOTQ1OjIwMTUKICBwbG90cGF0aDogUExPVFMvCi0tLQoKIyBPYmplY3RpdmVzCgpUaGlzIG5vdGVib29rIGFpbXMgYXQKCiAgLSB3b3JraW5nIHdpdGggKip0YWJsZXMqKiAoYGRhdGEuZnJhbWVzYCwgYHRpYmJsZXNgLCBgZGF0YS50YWJsZXNgLCAuLi4pIHVzaW5nIGBkcGx5cmAgb3IgYW55IG90aGVyIHF1ZXJ5IGxhbmd1YWdlIChhcyBwcm92aWRlZCBmb3IgZXhhbXBsZSBieSBgZGF0YS50YWJsZWApCiAgLSB2aXN1YWxpemluZyBkZW1vZ3JhcGhpYyBkYXRhIGFzIHByb3ZpZGVkIGJ5IFtIdW1hbiBNb3J0YWxpdHkgRGF0YWJhc2Ugb3JnYW5pemF0aW9uXShodHRwczovL3d3dy5tb3J0YWxpdHkub3JnKS4KICAtIHVzaW5nIFBDQSBhbmQgb3RoZXIgbWF0cml4IG9yaWVudGVkIG1ldGhvZHMgKENDQSkgdG8gZXhwbG9yZSBhIG11bHRpdmFyaWF0ZSBkYXRhc2V0cyAobGlmZXRhYmxlcyBtYXkgYmUgY29uc2lkZXJlZCBhcyBtdWx0aXZhcmlhdGUgZGF0YXNldHMpCgojIExpZmUgdGFibGVzIGRhdGEgKEVUTCkKCkxpZmUgZGF0YSB0YWJsZXMgYXJlIGRvd25sb2FkZWQgZnJvbSBbaHR0cHM6Ly93d3cubW9ydGFsaXR5Lm9yZ10oaHR0cHM6Ly93d3cubW9ydGFsaXR5Lm9yZykuCgpTZWUgYWxzbyBbaHR0cHM6Ly93d3cubGlmZXRhYmxlLmRlXShodHRwczovL3d3dy5saWZldGFibGUuZGUpLgoKV2UgaW52ZXN0aWdhdGUgbGlmZSB0YWJsZXMgZGVzY3JpYmluZyBjb3VudHJpZXMgZnJvbSBXZXN0ZXJuIEV1cm9wZSAoRnJhbmNlLCBHcmVhdCBCcml0YWluIC0tYWN0dWFsbHkgRW5nbGFuZCBhbmQgV2FsZXMtLSwgSXRhbHksIHRoZSBOZXRoZXJsYW5kcywgU3BhaW4sIGFuZCBTd2VkZW4pIGFuZCB0aGUgVW5pdGVkIFN0YXRlcy4KCldlIGxvYWQgdGhlIG9uZS15ZWFyIGxpZmV0YWJsZXMgZm9yIGZlbWFsZSwgbWFsZSBhbmQgd2hvbGUgcG9wdWxhdGlvbiBmb3IgdGhlIGRpZmZlcmVudCBjb3VudHJpZXMuCgpgYGB7ciwgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0KIyBmb3IgZGVidWdnaW5nCiMgcGFyYW1zIHNob3VsZCBiZSBpbml0aWFsaXplZCBmcm9tIFlBTUwgaGVhZGVyCnBhcmFtcyA8LSBsaXN0KAogICAgdGltZWNvdXJzZSA9IDE5NDU6MjAxNSwKICAgIGRpcnBhdGggPSAnTElGRV9UQUJMRVMvJywKICAgIGNvdW50cnlfY29kZSA9ICdmcl90JywKICAgIGNvdW50cnkgPSAnRnJhbmNlJywKICAgIHBsb3RwYXRoID0gIlBMT1RTLyIpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnRpbWVjb3Vyc2UgPC0gZXZhbChybGFuZzo6cGFyc2VfZXhwcihwYXJhbXMkdGltZWNvdXJzZSkpCmBgYAoKYGBge3IgdGlkeXZlcnNlLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBlY2hvPUZBTFNFfQpwYWNtYW46OnBfbG9hZChwbHlyKQpwYWNtYW46OnBfbG9hZChkcGx5cikKcGFjbWFuOjpwX2xvYWQodGlkeXZlcnNlKQpwYWNtYW46OnBfbG9hZChwbG90bHkpCnBhY21hbjo6cF9sb2FkKGZvcmVhY2gpCnBhY21hbjo6cF9sb2FkKGl0ZXJhdG9ycykKcGFjbWFuOjpwX2xvYWQoRFQpCnBhY21hbjo6cF9sb2FkKGFkZTQpCnBhY21hbjo6cF9sb2FkKEZhY3RvTWluZVIpCnBhY21hbjo6cF9sb2FkKGZhY3RvZXh0cmEpCnBhY21hbjo6cF9sb2FkKEZhY3RvSW52ZXN0aWdhdGUpCnBhY21hbjo6cF9sb2FkKGdnZm9ydGlmeSkKcGFjbWFuOjpwX2xvYWQoZ2d0aGVtZXMpCnBhY21hbjo6cF9sb2FkKEJpb2NNYW5hZ2VyKQpwYWNtYW46OnBfbG9hZChkZW1vZ3JhcGh5KQpwYWNtYW46OnBfbG9hZChnZ2JpcGxvdCkKcGFjbWFuOjpwX2xvYWQoY29ycnBsb3QpCnBhY21hbjo6cF9sb2FkKFJTcGVjdHJhKQpwYWNtYW46OnBfbG9hZChnZ2FsdCkKCiNvbGRfdGhlbWUgPC10aGVtZV9zZXQodGhlbWVfZGFyayhiYXNlX3NpemU9OSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhc2VfZmFtaWx5ID0gIkhlbHZldGljYSIpKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KGV2YWw9VFJVRSwKICBlY2hvPUZBTFNFLAogIHdhcm5pbmcgPSBGQUxTRSwKICBtZXNzYWdlID0gRkFMU0UsCiAgY2FjaGUgPSBUUlVFLAogIGF1dG9kZXAgPSBUUlVFLAogIHRpZHkgPSBUUlVFKQoKYGBgCgoKYGBge3IsIGVjaG89RkFMU0V9CmNvdW50cnlfY29kZSA8LSBsaXN0KGZyX3Q9J0ZSQVROUCcsCiAgICAgICAgICAgICAgICAgICAgIGZyX2M9J0ZSQUNOUCcsCiAgICAgICAgICAgICAgICAgICAgIGJlPSdCRUwnLAogICAgICAgICAgICAgICAgICAgICBnYl90PSdHQlJURU5XJywKICAgICAgICAgICAgICAgICAgICAgZ2JfYz0nR0JSQ0VOVycsCiAgICAgICAgICAgICAgICAgICAgIG5sPSdOTEQnLAogICAgICAgICAgICAgICAgICAgICBpdD0nSVRBJywKICAgICAgICAgICAgICAgICAgICAgc3dlPSdTV0UnLAogICAgICAgICAgICAgICAgICAgICBzcD0nRVNQJywKICAgICAgICAgICAgICAgICAgICAgdXM9J1VTQScpCgpjb3VudHJpZXMgPC0gYygnZnJfdCcsICAnZ2JfdCcsICAnbmwnLCAnaXQnLCAnc3AnLCAnc3dlJywgJ3VzJykKCmNvdW50cnlfbmFtZXMgPC0gbGlzdChmcl90PSdGcmFuY2UnLCAgICAgIyB0b3RhbCBwb3B1bGF0aW9uCiAgICAgICAgICAgICAgICAgICAgIGZyX2M9J0ZyYW5jZScsICAgICAgIyBjaXZpbGlhbiBwb3B1bGF0aW9uCiAgICAgICAgICAgICAgICAgICAgIGJlPSdCZWxnaXVtJywKICAgICAgICAgICAgICAgICAgICAgZ2JfdD0nRW5nbGFuZCAmIFdhbGVzJywgICAgIyB0b3RhbCBwb3B1bGF0aW9uCiAgICAgICAgICAgICAgICAgICAgIGdiX2M9J0VuZ2xhbmQgJiBXYWxlcycsICAgICMgY2l2aWxpYW4gcG9wdWxhdGlvbgogICAgICAgICAgICAgICAgICAgICBubD0nTmV0aGVybGFuZHMnLAogICAgICAgICAgICAgICAgICAgICBpdD0nSXRhbHknLAogICAgICAgICAgICAgICAgICAgICBzd2U9J1N3ZWRlbicsCiAgICAgICAgICAgICAgICAgICAgIHNwPSdTcGFpbicsCiAgICAgICAgICAgICAgICAgICAgIHVzPSdVU0EnKQoKZ2VuZGVyX25hbWVzIDwtIGxpc3QoJ2InPSdCb3RoJywKICAgICAgICAgICAgICAgICAgICAgJ2YnPSdGZW1hbGUnLAogICAgICAgICAgICAgICAgICAgICAnbSc9J01hbGUnKQpgYGAKCgojIyBSZXR5cGFnZQoKV2UgYmVnaW4gYnkgcmV0eXBpbmcgdGhlIGNvbHVtbnMuIFRoZSBzY2hlbWEgb2YgYGRmYCwgb3VyIHVuaXZlcnNhbCB0YWJsZSwgaXMgdGhlIGZvbGxvd2luZyA6Cgp8IENvbHVtbiBOYW1lIHwgQ29sdW1uIFR5cGUgfAp8Oi0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tfAp8ICBZZWFyICAgICAgIHwgaW50ZWdlciAgICAgfAp8ICBBZ2UgICAgICAgIHwgaW50ZWdlciAgICAgfAp8ICBteCAgICAgICAgIHwgZG91YmxlICAgICAgfAp8ICBxeCAgICAgICAgIHwgZG91YmxlICAgICAgfAp8ICBheCAgICAgICAgIHwgZG91YmxlICAgICAgfAp8ICBseCAgICAgICAgIHwgaW50ZWdlciAgICAgfAp8ICBkeCAgICAgICAgIHwgaW50ZWdlciAgICAgfAp8ICBMeCAgICAgICAgIHwgaW50ZWdlciAgICAgfAp8ICBUeCAgICAgICAgIHwgaW50ZWdlciAgICAgfAp8ICBleCAgICAgICAgIHwgZG91YmxlICAgICAgfAp8ICBDb3VudHJ5ICAgIHwgZmFjdG9yICAgICAgfAp8ICBHZW5kZXIgICAgIHwgZmFjdG9yICAgICAgfAoKSW4gb3JkZXIgdG8gYXZvaWQgY29lcmNpb24gcHJvYmxlbXMgYW5kIE5BIHdhcm5pbmdzLCB0aGUgY29sdW1uIGBBZ2VgIDogYDExMCtgLCBpcyBwcm9jZXNzZWQgYXMgYEFnZWAgOiBgMTEwYC4KCmBgYHtyfQpkZiA8LSBkYXRhLmZyYW1lKAogIFllYXIgPSBpbnRlZ2VyKCksCiAgQWdlID0gaW50ZWdlcigpLAogIG14ID0gZG91YmxlKCksCiAgcXggPSBkb3VibGUoKSwKICBheCA9IG51bWVyaWMoKSwKICBseCA9IGludGVnZXIoKSwKICBkeCA9IGludGVnZXIoKSwKICBMWCA9IGludGVnZXIoKSwKICBUeCA9IGludGVnZXIoKSwKICBleCA9IGRvdWJsZSgpLAogIENvdW50cnkgPSBmYWN0b3IoKSwKICBHZW5kZXIgPSBmYWN0b3IoKQopCgpmb3IgKGMgaW4gY291bnRyaWVzKXsKICBmb3IgKGUgaW4gbmFtZXMoZ2VuZGVyX25hbWVzKSkgewogICAgZiA8LSBwYXN0ZShwYXJhbXMkZGlycGF0aCwKICAgICAgICAgICAibHRfIiwKICAgICAgICAgICB0b2xvd2VyKGdlbmRlcl9uYW1lc1tbZV1dKSwgIi8iLAogICAgICAgICAgIGUsICJsdHBlcl8xeDEiLCAiLyIsCiAgICAgICAgICAgY291bnRyeV9jb2RlW1tjXV0sICIuIiwgZSwibHRwZXJfMXgxLnR4dCIsCiAgICAgICAgICAgc2VwID0gIiIKICAgICAgICAgICApCgogICAgZGZfYmlzIDwtcmVhZC50YWJsZSgKICAgICAgZmlsZSA9IGYsCiAgICAgIGhlYWRlciA9IFRSVUUsCiAgICAgIHNlcCA9ICIiLAogICAgICBkZWMgPSAiLiIsCiAgICAgIHNraXAgPSAyKQoKICAgIGRmX2JpcyRDb3VudHJ5IDwtIGNvdW50cnlfbmFtZXNbW2NdXQogICAgZGZfYmlzJEdlbmRlciA8LSBnZW5kZXJfbmFtZXNbW2VdXQoKICAgIGRmIDwtIHJiaW5kKGRmLCBkZl9iaXMpCiAgfQp9CgpkZiRBZ2UgPC0gYXMuaW50ZWdlcigKICAgICAgaWZlbHNlKAogICAgICAgIHN1YnN0cmluZyhkZiRBZ2UsIG5jaGFyKGRmJEFnZSksIG5jaGFyKGRmJEFnZSkpID09ICcrJywKICAgICAgICBzdWJzdHJpbmcoZGYkQWdlLCAwLCBuY2hhcihkZiRBZ2UpIC0gMSksCiAgICAgICAgZGYkQWdlCiAgICAgICAgKQogICAgICApCmRmJFllYXIgPC0gYXMuaW50ZWdlcihzdWJzdHJpbmcoZGYkWWVhciwgMCwgNCkpCmRmJENvdW50cnkgPC0gYXMuZmFjdG9yKGRmJENvdW50cnkpCmRmJEdlbmRlciA8LSBhcy5mYWN0b3IoZGYkR2VuZGVyKQoKIyBDbGVhbgpybShkZl9iaXMsIGYsIGMsIGUpCmBgYAoKIyMgV2VzdGVybiBjb3VudHJpZXMgaW4gMTk0OAoKSGVyZSB3ZSBwbG90IHRoZSBjZW50cmFsIGRlYXRoIHJhdGVzIG9mIGFsbCBDb3VudHJpZXMgYXQgYWxsIGFnZXMgZm9yIHRoZSB5ZWFyIDE5NDguCgpgYGB7cn0KZyA9IGxpc3QoYygnYicsICdmJywgJ20nKSkKCmZvciAoZSBpbiBuYW1lcyhnZW5kZXJfbmFtZXMpKSB7CiAgZ1tbZV1dIDwtIGRmICU+JQogICAgZmlsdGVyKFllYXI9PTE5NDgsIEdlbmRlcj09Z2VuZGVyX25hbWVzW1tlXV0pICU+JQogICAgZ2dwbG90KG1hcHBpbmc9YWVzKHg9QWdlLCB5PW14LCBjb2xvdXI9Q291bnRyeSwgbG9nID0gInkiKSkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGdlb21fbGluZSgpICsKICAgIGdndGl0bGUocGFzdGUoIkNlbnRyYWwgRGVhdGggUmF0ZXMgZm9yIiwgZ2VuZGVyX25hbWVzW1tlXV0sICIgZ2VuZGVyIGluIDE5NDgiLCBzZXA9IiAiKSkKfQpgYGAKCmBgYHtyIENlbnRyYWwgRGVhdGggcmF0ZSAxOTQ4fQpwbCA8LSBkZiAlPiUKICAgIGZpbHRlcihZZWFyPT0xOTQ4KSAlPiUKICAgIGdncGxvdChtYXBwaW5nPWFlcyh4PUFnZSwgeT1teCwgY29sb3VyPUNvdW50cnkpKSArCiAgICBzY2FsZV95X2xvZzEwKCkgKwogICAgZ2VvbV9saW5lKCkgKwogICAgZ2d0aXRsZSgiQ2VudHJhbCBEZWF0aCBSYXRlcyBwZXIgQ291bnRyeSAgYW5kIHBlciBHZW5kZXIgaW4gMTk0OCIpICsKICAgIGZhY2V0X2dyaWQoR2VuZGVyIH4gLikKCmdnc2F2ZShwbCwgZmlsZW5hbWUgPSBwYXN0ZShwYXJhbXMkcGxvdHBhdGgsICJjZHcucG5nIiwgc2VwPSIiKSwgZGV2aWNlPU5VTEwsIGhlaWdodCA9IDMgKiAzLCB3aWR0aCA9IDcpCmBgYAohW3Bsb3RdKFBMT1RTL2Nkdy5wbmcpCgpTcGFpbiBhbmQgSXRhbHkgaGF2ZSBoaWdoZXIgZGVhdGggcmF0ZXMgdGhhbiB0aGUgb3RoZXIgY291bnRyaWVzIGZyb20gMCB0byAzMC00NS4KCldlIGNhbiBzZWUgdGhhdCB0aGUgbG93ZXIgY2VudHJhbCBkZWF0aCByYXRlcyBhcmUgYmV0d2VlbiAxIGFuZCAxNSB5ZWFycyBvbGQuIEJldHdlZW4gMTUgYW5kIDMwIHllYXJzIG9sZCwgdGhpcyByYXRlIHNlZW1zIHRvIGluY3JlYXNlIGEgYml0LCBhbmQgcGFzdCAzMCB5ZWFycyBvbGQsIHRoZSBncmFwaCBmb2xsb3dzIGEgbGluZWFyIGZ1bmN0aW9uLCBtZWFuaW5nIHRoYXQgdGhlIHByb2JhYmlsaXR5IG9mIGR5aW5nIHBhc3QgMzAgeWVhcnMgb2xkIGJlY29tZSBhbG1vc3QgcHJvcG9ydGlvbmFsIHRvIHRoZSBhZ2UuCgpXZSBhbHNvIG5vdGljZSB0aGF0IHRoZSB3b21lbiBoYXZlIGxvd2VyIGRlYXRoIHJhdGVzIHRoYW4gbWVuLgoKYGBge3IgcmF0aW8gZGZ9CmRmX3JhdGlvIDwtIGZpbHRlcihkZiwgWWVhciA9PSAxOTQ4LCBDb3VudHJ5ICE9ICJVU0EiKVssYygiQWdlIiwgIm14IiwgIkNvdW50cnkiLCAiR2VuZGVyIildCmRmX3VzYSA8LSBmaWx0ZXIoZGYsIFllYXIgPT0gMTk0OCwgQ291bnRyeSA9PSAiVVNBIilbLGMoIkFnZSIgLCJteCIsICJHZW5kZXIiKV0gJT4lIGRwbHlyOjpyZW5hbWUoIm14LnVzYSI9Im14IikKYGBgCmBgYHtyIHJhdGlvIGNhbGN9CmRmX3JhdGlvIDwtIG1lcmdlKGRmX3JhdGlvLCBkZl91c2EsIGJ5PWMoIkFnZSIsICJHZW5kZXIiKSkKZGZfcmF0aW8gPC0gdHJhbnNmb3JtKGRmX3JhdGlvLCBsb2dfcmF0aW8gPSBsb2cobXgpIC8gbG9nKG14LnVzYSkpCmRmX3JhdGlvIDwtIHRyYW5zZm9ybShkZl9yYXRpbywgcmF0aW8gPSBteCAvIG14LnVzYSkKYGBgCmBgYHtyIHJhdGlvIHBsb3R9CnBsIDwtIGRmX3JhdGlvICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHg9QWdlLCB5PXJhdGlvLCBjb2xvdXI9Q291bnRyeSkpICsKICBzY2FsZV95X2xvZzEwKCkgKwogIGdndGl0bGUoIlJhdGlvIG9mIHRoZSBDRFIgYmV0d2VlbiBldXJvcGVhbiBjb3VudHJpZXNcbiAgYW5kIFVTQSBieSBnZW5kZXIgaW4gMTk0OCIpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfZ3JpZChHZW5kZXIgfiAuKSArCiAgbGFicyh5PSJyYXRpbyAgRVUgLyBVU0EiKQoKZ2dzYXZlKHBsLCBmaWxlbmFtZSA9IHBhc3RlKHBhcmFtcyRwbG90cGF0aCwgImNkdzMucG5nIiwgc2VwPSIiKSwgZGV2aWNlPU5VTEwsIGhlaWdodCA9IDMgKiAzLCB3aWR0aCA9IDYpCmBgYAohW10oUExPVFMvY2R3My5wbmcpCgpXZSBjYW4gc2VlIHRoYXQgYmV0d2VlbiAwIGFuZCA0NSB5ZWFycyBvbGQgRnJhbmNlLCBTcGFpbiBhbmQgSXRhbHkgaGF2ZSBoaWdoZXIgY2VudHJhbCBkZWF0aCByYXRlcyB0aGFuIFVTQSwgd2hpbGUgdGhlIG90aGVycyBjb3VudHJpZXMgaGF2ZSBzaW1pbGFyIG9yIGxvd2VyIGRlYXRoIHJhdGVzLgpJbmZhbnQgbW9ydGFsaXR5IHBlYWtzIGlzIDUgdGltZXMgbW9yZSBpbXBvcnRhbnQgaW4gSXRhbHkgYW5kIFNwYWluIHRoYW4gaW4gdGhlIFVTLgpIb3dldmVyLCBpbiBTd2VkZW4gYW5kIE5ldGhlcmxhbmRzIHRoZSBkZWF0aF9yYXRlcyBhcmUgbG93ZXIgdGhhbiBpbiB0aGUgVVMsIGVzcGVjaWFsbHkgZm9yIG1lbiBiZXR3ZWVuIDMwIGFuZCA2MCB5ZWFycyBvbGQsIHRoZSBtb3J0YWxpdHkgaXMgYWxtb3N0IGhhbGYgb2YgdGhlIGFtZXJpY2FuIG9uZS4KQmV0d2VlbiA0NSBhbmQgNzUgeWVhcnMgb2xkIGV1cm9wZWFuIGNvdW50cmllcyBoYXZlIGxvd2VyIGRlYXRoIHJhdGVzIHRoYW4gYW1lcmljYS4KUGFzdCA3NSB5ZWFycyBvbGQsIHRoZSBkaXNwYXJpdGllcyBzb290aCwgZXhjZXB0IG1heWJlIGZvciBTcGFuaXNoIHdvbWVuIHdobyBoYXZlIGEgbWlub3IgbW9ydGFsaXR5LgoKCiMjIERlYXRoIHJhdGVzIGV2b2x1dGlvbiBzaW5jZSBXV0lJCgpOb3cgd2Ugd2lsbCB0YWtlIGEgbG9vayBhdCB0aGUgZXZvbHV0aW9uIG9mIGRlYXRoIHJhdGVzIGFmdGVyIHRoZSBzZWNvbmQgd29ybGQgd2FyLiBXZSBwbG90IHRoZSBjZW50cmFsIGRlYXRoIHJhdGVzIGFzIGEgZnVuY3Rpb24gb2YgQWdlIGZvciB0aGUgeWVhcnMgMTk0NiwgMTk1NiwgMTk2NiwgLi4uICwgMjAxNi4KCmBgYHtyIGNkdyAyLCB3YXJuaW5nPVRSVUV9CnBsIDwtIGRmICU+JSBmaWx0ZXIoWWVhciAlaW4lIHNlcSgxOTQ2LCAyMDE2LCBieT0xMCkpICU+JQogICAgZ2dwbG90KG1hcHBpbmc9YWVzKHg9QWdlLCB5PW14LCBjb2xvdXI9YXMuZmFjdG9yKFllYXIpKSkgKwogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGdlb21fbGluZSgpICsKICAgIGdndGl0bGUoIkNlbnRyYWwgRGVhdGggUmF0ZXMgYnkgY291bnRyeSBhbmQgZ2VuZGVyIGZyb20gMTk0NiB0byAyMDE2IikgKwogICAgbGFicyhjb2xvdXI9IlllYXIiKSArCiAgICBmYWNldF9ncmlkKENvdW50cnkgfiBHZW5kZXIpCmBgYAoKYGBge3J9Cmdnc2F2ZShwbCwgZmlsZW5hbWUgPSBwYXN0ZShwYXJhbXMkcGxvdHBhdGgsICJjZHcyLnBuZyIsIHNlcD0iIiksIGRldmljZT1OVUxMLCBoZWlnaHQgPSA4ICogMSwgd2lkdGggPSAzKjIpCmBgYAoKIVtdKFBMT1RTL2NkdzIucG5nKQoKV2UgY2FuIHNlZSB0aGF0IHRoZSBtb3J0YWxpdHkgcXVvdGllbnRzICBoYXZlIGRlY3JlYXNlZCBkZWNhZGUgYnkgZGVjYWRlLCBlc3BlY2lhbGx5IGF0IGJpcnRoLCBhbmQgYXJlIGdlbmVyYWxseSBhdCB0aGVpciBsb3dlc3QgZm9yIHRoZSB5ZWFyIDIwMTYuCldlIG9ic2VydmUgdGhlIHNhbWUgcGhlbm9tZW5vbiBkdXJpbmcgYWxsIHRoZXNlIHllYXJzIHRoYW4gaW4gMTk0OCwgdGhlIGNlbnRyYWwgZGVhdGggcmF0ZXMgYXJlIGxvdyBmcm9tIDEgdG8gMTUsIHRoZW4gaW5jcmVhc2UgYW5kIHJlYWNoIGEgcGVhayBhcm91bmQgMjUgeWVhcnMgb2xkLCBhbmQgZmluYWxseSBzZWVtcyB0byBpbmNyZWFzZSBwcm9wb3J0aW9uYWx5IGZyb20gMzAgeWVhcnMgb2xkLgpXZSBhbHNvIHNlZSB0aGF0IHdvbWVuIGhhdmUgbG93ZXIgZGVhdGggcmF0ZXMgdGhhbiBtZW4sIGZvciBhbGwgY291bnRyaWVzLgoKVGhlIHBlYWsgYXJvdW5kIDI1IHllYXJzIG9sZCBpcyByZWFsbHkgbm90aWNlYWJsZSBmb3IgdGhlIG1lbiBpbiBhbGwgY291bnRyaWVzLCB3aGlsZSBmb3Igd29tZW4gaXQgaXNuJ3QgYXMgdmlzaWJsZS4gVGhpcyBtYXkgYmUgY2F1c2UgYnkgc3VpY2lkZSwgYmVjYXVzZSB3aGlsZSB3b21lbiBoYXZlIGFuIGhpZ2hlciBhdHRlbXB0ZWQgc3VpY2lkZSByaXNrcywgbWVuIHRlbmQgdG8gZW1wbG95IG1vcmUgcmFkaWNhbCBtZXRob2RzIHRvIGtpbGwgdGhlbXNlbGZzLiBJbiAyMDA4IHRoZSBtYWxlLWZlbWFsZSByYXRlIHJhdGlvIG9mIHN1aWNpZGUgaW4gRXVyb3BlIHdhcyA0LjAgYW5kIGluIHRoZSBVU0EgMy42LCBhY2NvcmRpbmcgdG8gW1N1aWNpZGUgaW4gdGhlIFdvcmxkLCBieSBQZWV0ZXIgVsOkcm5pa10oaHR0cHM6Ly93d3cubWRwaS5jb20vMTY2MC00NjAxLzkvMy83NjAvaHRtKS4KQW4gb3RoZXIgZmFjdG9yIG1pZ2h0IGJlIHRoZSBoaWdoZXIgcHJvcG90aW9uIG9mIG1lbiBkeWluZyBpbiBtb3RvciB2ZWhpY2xlIGNyYXNoZXMsIGZvciBleGFtcGxlIGluIDIwMTggNzElIG9mIG1vdG9yIHZlaGljdWxlIGRlYXRocyB3ZXJlIG1lbiBpbiB0aGUgVVMuIE1lbiB0ZW5kIHRvIGhhdmUgbW9yZSBoaWdoIHJpc2tzIGRyaXZpbmcgcHJhY3RpY2VzIHRoYW4gd29tZW4sIGluIDIwMDggNDAlIG9mIG1hbGVzIGRyaXZlcnMga2lsbGVkIG9uIHRoZSByb2FkIGhhZCBCQUNzIOKJpSAwLjA4IHBlcmNlbnQsIGFnYWluc3QgMjAlIGZvciBmZW1hbGVzLiBBbGwgb2YgdGhlc2UgbnVtYmVyIGNvbWUgZnJvbSB0aGlzIFthbmFseXNpcyBvZiBkYXRhIGZyb20gdGhlIFUuUy4gRGVwYXJ0bWVudCBvZiBUcmFuc3BvcnRhdGlvbidzIEZhdGFsaXR5IEFuYWx5c2lzIFJlcG9ydGluZyBTeXN0ZW0gKEZBUlMpXShodHRwczovL3d3dy5paWhzLm9yZy90b3BpY3MvZmF0YWxpdHktc3RhdGlzdGljcy9kZXRhaWwvZ2VuZGVyI2FnZS1kaWZmZXJlbmNlcykuCgpUaGlzIHNwaWtlIGFwcGVhcnMgaW4gMTk1NiBhbmQgMTk2NiwgbWFraW5nIHRoZSBtYWxlJ3MgY3VydmUgZGl2ZXJnZSBmcm9tIHRoZSB3b21lbiBvbmUsIGJ1dCB0ZW5kIHRvIGZsYXR0ZW4gaW4gMjAwNiBhbmQgMjAxNiBleGNlcHQgaW4gdGhlIFVTLgoKV2Ugb2JzZXJ2ZSB0aGF0IHRoZSBtb3J0YWxpdHkgcXVvdGllbnRzIGZvciBVU0EgYXJlIGhpZ2hlciB0aGFuIHRoZSBldXJvcGVhbiBvbmVzLgoKSGVyZSB0aGUgZnVuY3Rpb24gcmF0aW9fbW9ydGFsaXR5X3JhdGVzYCB3aXRoIHNpZ25hdHVyZQpgZnVuY3Rpb24oZGYsIHJlZmVyZW5jZV95ZWFyPTE5NDYsIHRhcmdldF95ZWFycz1zZXEoMTk0NiwgMjAxNiwgMTApKWAgdGhhdCB0YWtlcyBhcyBpbnB1dCA6CgogIC0gYSBkYXRhZnJhbWUgd2l0aCB0aGUgc2FtZSBzY2hlbWEgYXMgYGxpZmVfdGFibGVgLAogIC0gYSByZWZlcmVuY2UgeWVhciBgcmVmX3llYXJgIGFuZAogIC0gYSBzZXF1ZW5jZSBvZiB5ZWFycyBgdGFyZ2V0X3llYXJzYAoKYW5kIHRoYXQgcmV0dXJucyBhIGRhdGFmcmFtZSB3aXRoIHNjaGVtYToKCgp8IENvbHVtbiBOYW1lIHwgQ29sdW1uIFR5cGUgfAp8Oi0tLS0tLS0tLS0tLXw6LS0tLS0tLS0tLS0tfAp8ICBZZWFyICAgICAgIHwgaW50ZWdlciAgICAgfAp8ICBBZ2UgICAgICAgIHwgaW50ZWdlciAgICAgfAp8ICBteCAgICAgICAgIHwgZG91YmxlICAgICAgfAp8ICBteC5yZWZfeWVhcnwgZG91YmxlICAgICAgfAp8ICBDb3VudHJ5ICAgIHwgZmFjdG9yICAgICAgfAp8ICBHZW5kZXIgICAgIHwgZmFjdG9yICAgICAgfAoKd2hlcmUgYChDb3VudHJ5LCBZZWFyLCBBZ2UsIEdlbmRlcilgIHNlcnZlcyBhcyBhIF9wcmltYXJ5IGtleV8sCmBteGAgZGVub3RlcyB0aGUgY2VudHJhbCBkZWF0aCByYXRlIGF0IGBBZ2VgIGZvciBgWWVhcmAgYW5kIGBHZW5kZXJgIGluIGBDb3VudHJ5YAp3aGVyZWFzIGBteF9yZWZfeWVhcmAgZGVub3RlcyBjZW50cmFsIGRlYXRoIHJhdGUgYXQgYEFnZWAgZm9yIGFyZ3VtZW50IGByZWZlcmVuY2VfeWVhcmAKaW4gYENvdW50cnlgIGZvciBgR2VuZGVyYC4KCmBgYHtyIHJhdGlvIG1vcnRhbGl0eSByYXRlcyBmdW5jdGlvbn0KcmF0aW9fbW9ydGFsaXR5X3JhdGVzIDwtIGZ1bmN0aW9uKGRmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmZXJlbmNlX3llYXI9MTk0NiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldF95ZWFycz1zZXEoMTk0NiwgMjAxNiwgMTApKXsKICBkZl9vdXQgPC0gZmlsdGVyKGRmLCBZZWFyICVpbiUgdGFyZ2V0X3llYXJzKVssYygiWWVhciIsICJBZ2UiLCAibXgiLCAiQ291bnRyeSIsICJHZW5kZXIiKV0KICBkZl9vdXQgPC0gbWVyZ2UoZGZfb3V0LCBmaWx0ZXIoZGYsIFllYXIgPT0gcmVmZXJlbmNlX3llYXIpWyxjKCJBZ2UiLCAibXgiLCAiQ291bnRyeSIsICJHZW5kZXIiKV0sIGJ5PWMoIkFnZSIsICJDb3VudHJ5IiwgIkdlbmRlciIpKQogIG5hbWVzKGRmX291dClbbmFtZXMoZGZfb3V0KSA9PSAibXgueSJdIDwtICJteC5yZWZfeWVhciIKICBuYW1lcyhkZl9vdXQpW25hbWVzKGRmX291dCkgPT0gIm14LngiXSA8LSAibXgiCgogIGRmX291dAp9CgpgYGAKCmBgYHtyIGRmIHJhdGVzfQpkZl9yYXRlcyA8LSByYXRpb19tb3J0YWxpdHlfcmF0ZXMoZGYpCmBgYAoKV2Ugbm93IGRyYXcgcGxvdHMgZGlzcGxheWluZyB0aGUgcmF0aW8gICRtX3t4LHR9L21fe3gsIDE5NDZ9JCBmb3IgYWdlcyAkeCBcaW4gMSwgXGxkb3RzLCA5MCQgYW5kIHllYXIgJHQkIGZvciAkdCBcaW4gMTk1NiwgXGxkb3RzLCAyMDE2JCB3aGVyZSAkbV97eCx0fSQgaXMgdGhlIGNlbnRyYWwgZGVhdGggcmF0ZSBhdCBhZ2UgJHgkIGR1cmluZyB5ZWFyICAkdCQuCgpgYGB7ciBwbG90IHJhdGVzfQoKcGwgPC0gZGZfcmF0ZXMgJT4lCiAgZmlsdGVyKFllYXIgIT0gMTk0NikgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeD1BZ2UsIHk9bXggLyBteC5yZWZfeWVhciwgY29sb3VyPWFzLmZhY3RvcihZZWFyKSkpICsKICBzY2FsZV95X2xvZzEwKCkgKwogIGdndGl0bGUoIlJhdGlvIG9mIENEUiBiZXR3ZWVuIGVhY2ggeWVhciBhbmQgMTk0NiBieSBjb3VudHJ5IGFuZCBnZW5kZXIiKSArCiAgZ2VvbV9saW5lKCkgKwogICNnZW9tX3hzcGxpbmUobWFwcGluZyA9IGFlcyh4PUFnZSwgeT1teCAvIG14LnJlZl95ZWFyLCBjb2xvdXI9YXMuZmFjdG9yKFllYXIpKSkgKwogICNnZW9tX3Ntb290aCgpKwogIGZhY2V0X2dyaWQoQ291bnRyeSB+IEdlbmRlcikgKwogIGxhYnMoY29sb3VyPSJZZWFyIiwgeT0icmF0aW8iKQoKIyBkZl90ZW1wIDwtIGZpbHRlcihkZl9yYXRlcywgWWVhciAhPSAxOTQ2KQpnZ3NhdmUocGwsIGZpbGVuYW1lID0gcGFzdGUocGFyYW1zJHBsb3RwYXRoLCAiY2R3NS5wbmciLCBzZXA9IiIpLCBkZXZpY2U9TlVMTCwgaGVpZ2h0ID0gNyAqIDIsIHdpZHRoID0gMyAqIDMpCmBgYAoKIVtdKFBMT1RTL2NkdzUucG5nKQoKV2Ugb2JzZXJ2ZSB0aGF0IHRoZSBjZW50cmFsIGRlYXRoIHJhdGVzIGhhcyBkZWNyZWFzZWQgZm9yIGV2ZXJ5IGNvdW50cnkgYW5kIGV2ZXJ5IGFnZSBzaW5jZSAxOTQ2LiBUaGUgaW5mYW50IG1vcnRhbGl0eSwgYmV0d2VlbiAwIGFuZCAxNSB5ZWFycyBvbGQsIGluIDIwMTYgaXMgMTAgdGltZXMgbG93ZXIgdGhhbiBpbiAxOTQ2IGluIEV1cm9wZWFuIGNvdW50cmllcy4gSXQgYXBwZWFycyB0aGF0IHRoZSBtb3J0YWxpdHkgb2YgdGhlIHdvbWVuIGhhcyBkZWNyZWFzZWQgdGhlIG1vc3Qgc2luY2UgMTk0Ni4KCkluIHRoZSBVUyB0aGlzIGRyb3AgaXMgbGVzcyBkcmFzdGljLCBhbmQgd2UgY2FuIG5vdGljZSB0aGF0IGFyb3VuZCAzMCBmb3IgbWFsZXMgZm9yIDIwMDYgYW5kIDIwMTYsIHRoZSByYXRpbyBkb2Vzbid0IGZvbGxvdyB0aGUgb3ZlcmFsbCBkaW1pbnVpdGlvbiB1bmxpa2UgaW4gdGhlIHByZXZpb3VzIGRlY2FkZS4gVGhlcmUgaXMgYSBzaW1pbGFyIHBoZW5vbWVub24gZm9yIGZlbWFsZXMsIGJ1dCBsZXNzIGltcG9ydGFudC4KCgojIFRyZW5kcwoKYGBge3IgY2R3IDAgMSA1fQpwbCA8LSBkZiAlPiUKICBmaWx0ZXIoQWdlICVpbiUgYygwLCAxLCA1KSkgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeD1ZZWFyLCB5PW14LCBjb2xvdXI9YXMuZmFjdG9yKEFnZSkpKSArCiAgc2NhbGVfeV9sb2cxMCgpKwogIGdndGl0bGUoIkNEUiBmb3IgY2hpbGRyZW4gYWdlZCAwLCAxIGFuZCA1IFxuIGFzIGEgZnVuY3Rpb24gb2YgdGltZSBieSBjb3VudHJ5IGFuZCBnZW5kZXIiKSArCiAgZ2VvbV9saW5lKCkgKwogIGZhY2V0X2dyaWQoQ291bnRyeSB+IEdlbmRlcikgKwogIGxhYnMoY29sb3VyPSJBZ2UiLCB5PSJyYXRpbyIpCmdnc2F2ZShwbCwgZmlsZW5hbWUgPSBwYXN0ZShwYXJhbXMkcGxvdHBhdGgsICJjZHc2LnBuZyIsIHNlcD0iIiksIGRldmljZT1OVUxMLCBoZWlnaHQgPSA3ICogMiwgd2lkdGggPSAzICogMykKYGBgCiFbXShQTE9UUy9jZHc2LnBuZykKT24gdGhlc2UgcGxvdHMsIHdlIGNhbiBzZWUgdGhhdCB0aGUgaW5mYW50IG1vcnRhbGl0eSBoYXMgZGVjcmVhc2VkIGFzIHRoZSB0aW1lIGdvbmUgYnksIHBhcnRpY3VsYXJseSBhdCBiaXJ0aCBhbmQgYXQgMSB5ZWFyIG9sZC4KVGhpcyBkaW1pbnVpdGlvbiBoYXMgc3BlZWQgdXAgc2luY2UgMTkxMCAtIDE5MzAgZGVwZW5kaW5nIG9mIHRoZSBjb3VudHJ5LCBhbmQgd2UgbWlnaHQgbGluayB0aGlzIHRvIHRoZSBkcmFzdGljIGNoYW5nZSBpbiBjaGlsZGJpcnRoLCBhbmQgZ2xvYmFsIGh5Z2llbmUgZHVyaW5nIHRoaXMgcGVyaW9kLgoKCmBgYHtyIGNkdyAxNSwgMjAsIDQwLCA2MH0KCnBsIDwtIGRmICU+JQogIGZpbHRlcihBZ2UgJWluJSBjKDE1LCAyMCwgNDAsIDYwKSkgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeD1ZZWFyLCB5PW14LCBjb2xvdXI9YXMuZmFjdG9yKEFnZSkpKSArCiAgc2NhbGVfeV9sb2cxMCgpICsKICBnZ3RpdGxlKCJDRFIgZm9yIGFnZXMgZGUgMTUsIDIwLCA0MCBldCA2MCB5ZWFycyBvbGRcbiBhcyBhIGZ1bmN0aW9uIG9mIHRpbWUgYnkgY291bnRyeSBhbmQgZ2VuZGVyIikgKwogIGdlb21fbGluZSgpICsKICBmYWNldF9ncmlkKENvdW50cnkgfiBHZW5kZXIpICsKICBsYWJzKGNvbG91cj0iQWdlIiwgeT0icmF0aW8iKQpnZ3NhdmUocGwsIGZpbGVuYW1lID0gcGFzdGUocGFyYW1zJHBsb3RwYXRoLCAiY2R3Ny5wbmciLCBzZXA9IiIpLCBkZXZpY2U9TlVMTCwgaGVpZ2h0ID0gNyAqIDIsIHdpZHRoID0gMyAqIDMpCmBgYAohW10oUExPVFMvY2R3Ny5wbmcpCgpPbmNlIGFnYWluIHdlIG9ic2VydmUgdGhlIGRlY3JlYXNpbmcgb2YgdGhlIG1vcnRhbGl0eSBxdW90aWVudHMgYXMgYSBmdW5jdGlvbiBvZiB0aW1lLgpGb3IgRXVyb3BlYW4gY291bnRyaWVzLCB3ZSBub3RpY2UgMiBwZWFrcyBtb3JlIGltcG9ydGFudHMgZm9yIG1lbiB0aGFuIGZlbWFsZSAoYWdlZCAxNSwgMjAgYW5kIDQwIHllYXJzIG9sZCkgY29ycmVzcG9uZGluZyB0byBXV0kgYW5kIFdXSUkgKGFuZCBzcGFuaXNoIGNpdmlsIHdhciBmb3IgU3BhaW4pLCBleGNlcHQgZm9yIFN3ZWRlbiB3aGljaCByZW1haW5kIG5ldXRyYWwgZHVyaW5nIHRoZSBzZWNvbmQgY29uZmxpY3QuClRoZXJlIGlzIGFsc28gYSBsaXR0bGUgcGVhayBmb3IgdGhlIFVTQSBtYWxlIGF0IDIwIGR1cmluZyBXV0lJLgpGb3IgRnJhbmNlIHdlIGNhbiBzZWUgb3RoZXJzIHBlYWtzIGZvciBtYWxlcyBhbmQgZmVtYWxlcyBhZnRlciAxODUwIGR1cmluZyB0aGUgRnJhbmNvLVBydXNzaWFuIFdhciwgYW5kIG90aGVyIGNvbmZsaWN0cyBpbiB0aGlzIHBlcmlvZC4KCldlIGFsc28gb2JzZXJ2ZSBhIG1ham9yIGRyb3AgZm9yIHdvbWVuIGF0IDE1IGFuZCAyMCB5ZWFycyBvbGQgZnJvbSBhbGwgY291bnRyaWVzIGFmdGVyIFdXSUksIHdoaWNoIG1pZ2h0IGJlIGxpbmtlZCwgYXMgZm9yIHRoZSBkcm9wIG9mIGluZmFudCBtb3J0YWxpdHksIHRvIHRoZSBwcm9ncmVzcyBtYWRlIHdpdGggZ2VuZXJhbCBoeWdpZW5lLCBkZWxpdmVyeSwgYW5kIHRoZSBlbmQgb2YgYmFyYmFyIG1ldGhvZCBzdWNoIGFzIHRoZSBbVHdpbGlnaHQgU2xlZXBdKGh0dHBzOi8vd3d3LmJlbGx5YmVsbHkuY29tLmF1L2JpcnRoL3R3aWxpZ2h0LXNsZWVwLykuCgojIFJlYXJyYW5nZW1lbnQKCgpOb3cgd2UgY29tcHV0ZSBhIG5ldyBkYXRhZnJhbWUgYGRmX3Bpdm90YCwgd2l0aCBwcmltYXJ5IGtleSAoYEdlbmRlcmAsYFllYXJgLGBDb3VudHJ5YCksIHdpdGggYSBjb2x1bW4gZm9yIGVhY2ggQWdlICBmcm9tIGAwYCB0byBgMTEwYC4KCmBgYHtyIHBpdm90fQpwaXYgPC0gZnVuY3Rpb24oZGYpIHsKICBkZiAlPiUgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoIkdlbmRlciIsICJZZWFyIiwgIkNvdW50cnkiKSwgbmFtZXNfZnJvbT1BZ2UsIHZhbHVlc19mcm9tPW14KQp9CmBgYAoKYGBge3IgcmVhcnJhbmdlbWVudH0KZGZfcGl2b3QgPC0gcGl2KGRmKQpgYGAKCgpBY2NvcmRpbmcgdG8gW2h0dHBzOi8vd3d3LmxpZmVleHBlY3RhbmN5Lm9yZy9saWZldGFibGUuc2h0bWxdKGh0dHBzOi8vd3d3LmxpZmVleHBlY3RhbmN5Lm9yZy9saWZldGFibGUuc2h0bWwpLCBsaWZlIGV4cGFuY3RhbmN5ICRlKHgpJCAgb2YgcGVyc29ucyBhbGl2ZSBhdCBhZ2UgJHgkIGlzIGNvbXB1dGVkIHdpdGggdGhlIGZvbGxvd2luZyBtZXRob2QgOgoKJCQKZSh4KSA9IFxmcmFjIHtUKHgpfSB7bCh4KX0KJCQKIHdoZXJlCgokJApsKHggKyAxKSA9IGwoeCkgXGNkb3QgZV57LW0oeCl9CiQkClNvIHdlIGhhdmUKJCQKbCh4ICsgMikgPSBsKHggKyAxKSBcY2RvdCBlXnstbSh4ICsgMSl9Cj0gbCh4KSBcY2RvdCBlXnstbSh4KX0gXGNkb3QgZV57LW0oeCArIDEpfQo9IGwoeCkgXGNkb3QgZV57LShtKHgpICsgbSh4ICsgMSkpfQokJApUaGVyZWZvcmUsICRcZm9yYWxsIG4gXGluIFt8MSwgMTEwIC0geHxdJDoKCiQkCmwoeCArIG4pID0gbCh4KSBcY2RvdCBlXnstXHN1bV97aSA9IDB9XntuIC0gMX0gbSh4ICsgaSl9CiQkCkFuZCBmb3IgJFQoeCkkOgokJApUKHgpID0gXHN1bV97biA9IDB9XnsxMTAgLSB4fSBMKHggKyBuKVxcCkwoeCkgPSBcZnJhYyAxIDIgKGwoeCkgKyBsKHggKyAxKSkgPSBcZnJhYyAxIDIgbCh4KSAoMSArIGVeey1tKHgpfSkKJCQKU28gJFxmb3JhbGwgbiBcaW4gW3wxLCAxMTAgLSB4fF0kCiQkCkwoeCArIG4pID0gXGZyYWMgMSAyIGwoeCArIG4pICgxICsgZV57LW0oeCArIG4pfSlcXCA9IFxmcmFjIDEgMiBsKHgpIFxjZG90IGVeey1cc3VtX3tpID0gMH1ee24gLSAxfSBtKHggKyBpKX0gKDEgKyBlXnstbSh4ICsgbil9KQokJApXaGljaCBnaXZlcyB1czoKJCQKVCh4KSA9IFxzdW1fe24gPSAwfV57MTEwIC0geH0gTCh4ICsgbikgPSBcZnJhYyAxIDIgbCh4KSAoMSArIGVeey1tKHgpfSkgKyBcc3VtX3tuID0gMX1eezExMCAtIHh9IFxmcmFjIDEgMiBsKHgpIFxjZG90IGVeey1cc3VtX3tpID0gMH1ee24gLSAxfSBtKHggKyBpKX0gKDEgKyBlXnstbSh4ICsgbil9KVxcCj0gXGZyYWMgMSAyIGwoeCkgXGNkb3QgWygxICsgZV57LW0oeCl9KSArIFxzdW1fe24gPSAxfV57MTEwIC0geH0gIGVeey1cc3VtX3tpID0gMH1ee24gLSAxfSBtKHggKyBpKX0gXGNkb3QgKDEgKyBlXnstbSh4ICsgbil9KV0KJCQKVGhpcyB3YXk6CgokJAplKHgpID0gXGZyYWMge1QoeCl9IHtsKHgpfSA9IFxmcmFjIDEgMiBcY2RvdCBbKDEgKyBlXnstbSh4KX0pICsgXHN1bV97biA9IDF9XnsxMTAgLSB4fSAgZV57LVxzdW1fe2kgPSAwfV57biAtIDF9IG0oeCArIGkpfSBcY2RvdCAoMSArIGVeey1tKHggKyBuKX0pXQokJAoKX18tIFsgXSBVc2luZyBgbGlmZV90YWJsZV9waXZvdGAgY29tcHV0ZSBsaWZlIGV4cGVjdGFuY3kgYXQgYmlydGggZm9yIGVhY2ggQ291bnRyeSwgR2VuZGVyIGFuZCBZZWFyX18KCiNMaWZlIGV4cGVjdGFuY3kKCmBsaWZlX2V4cGVjdGFuY3lgIGlzIGEgZnVuY3Rpb24gdGhhdCB0YWtlcyBhcyBpbnB1dCBhIHZlY3RvciBvZiBtb3J0YWxpdHkgcXVvdGllbnRzLCBhcyB3ZWxsIGFzIGFuIGFnZSwgYW5kIHJldHVybnMgdGhlIHJlc2lkdWFsIGxpZmUgZXhwZWN0YW5jeSBjb3JyZXNwb25kaW5nIHRvIHRoZSB2ZWN0b3IgYW5kIHRoZSBnaXZlbiBhZ2UuCgpgYGB7cn0KIyAwIDw9IGZyb20gPCAxMTAKbGlmZV9leHBlY3RhbmN5IDwtIGZ1bmN0aW9uKGRmLCBmcm9tPTAsIG1heC5hZ2UgPSAxMTApIHsKICBtIDwtIGRmW2FzLmNoYXJhY3Rlcihmcm9tKV0gIyBzdW0gaSA9IDAgLT4gbiAtIDEgb2YgbSh4ICsgaSkKICBlIDwtIDEgKyBleHAoLW0pICMgbGlmZSBleHBlY3RhbmN5CgogIGlmKGZyb20gPCBtYXguYWdlKQogICAgZm9yIChhIGluIGFzLmNoYXJhY3RlcihjKChmcm9tICsgMSk6bWF4LmFnZSkpKSB7CiAgICAgIGUgPC0gZSArIChleHAoLW0pICogKDEgKyBleHAoLWRmW2FdKSkpCiAgICAgIG0gPC0gbSArIGRmW2FdCiAgICB9CiAgZSAvIDIKfQpgYGAKClRoZW4gd2UgaGF2ZSBgbGlmZV9leHBlY3RhbmN5X2FsbGAsIGEgZnVuY3Rpb24gdGhhdCB0YWtlcyBhcyBpbnB1dCBhIGRhdGFmcmFtZSB3aXRoIHRoZSBzYW1lIHNjaGVtYSBhcyAgYGxpZmVfdGFibGVgIGFuZCByZXR1cm5zIGEgZGF0YSBmcmFtZSB3aXRoIGNvbHVtbnMgYENvdW50cnlgLCBgR2VuZGVyYCwgYFllYXJgLCBgQWdlYCBkZWZpbmluZyBhIHByaW1hcnkga2V5IGFuZCBhIGNvbHVtbiBgcmVzX2xleGAgY29udGFpbmluZyBfcmVzaWR1YWwgbGlmZSBleHBlY3RhbmN5XyBjb3JyZXNwb25kaW5nIHRvIHRoZSBwaW1hcnkga2V5LgoKYGBge3J9CmxpZmVfZXhwZWN0YW5jeV9hbGwgPC0gZnVuY3Rpb24oZGYsIGhhcy5jb3VudHJ5ID0gVFJVRSwgbWF4LmFnZSA9IDExMCwgaGFzLmdlbmRlciA9IFRSVUUpIHsKICBjb2xzID0KICAgIGlmKGhhcy5jb3VudHJ5KQogICAgICAoaWYoaGFzLmdlbmRlcikKICAgICAgICBjKCJHZW5kZXIiLCAiWWVhciIsICJDb3VudHJ5IikKICAgICAgIGVsc2UKICAgICAgICAgYygiWWVhciIsICJDb3VudHJ5IikpCiAgICBlbHNlICgKICAgICAgaWYgKGhhcy5nZW5kZXIpCiAgICAgICAgYygiR2VuZGVyIiwgIlllYXIiKQogICAgICBlbHNlIGMoIlllYXIiKQogICAgICApCgogIGRmX3Bpdm90IDwtIGRmICU+JSBwaXZvdF93aWRlcihpZF9jb2xzID0gY29scywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZXNfZnJvbT1BZ2UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc19mcm9tPW14KQogIGZvciAoZSBpbiBjKDA6bWF4LmFnZSkpIHsKICAgIGRmX3Bpdm90W2FzLmNoYXJhY3RlcihlKV0gPC0gbGlmZV9leHBlY3RhbmN5KGRmX3Bpdm90LCBlLCBtYXguYWdlKQogIH0KICBkZl9leHBlY3RhbmN5IDwtIGRmX3Bpdm90ICU+JSBwaXZvdF9sb25nZXIoLWNvbHMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIkFnZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJyZXNfbGV4IikKICBkZl9leHBlY3RhbmN5JEFnZSA8LSBhcy5pbnRlZ2VyKGRmX2V4cGVjdGFuY3kkQWdlKQogIGRmX2V4cGVjdGFuY3kKfQpgYGAKCmBgYHtyIGxpZmVfZXhwZWN0YW5jeV9hbGx9CmRmX2V4cGVjdGFuY3kgPC0gbGlmZV9leHBlY3RhbmN5X2FsbChkZikKYGBgCldlIHBsb3QgdGhlIGxpZmUgZXhwZWN0YW5jeSBhdCBiaXJ0aCBmb3IgZWFjaCBjb3VudHJ5LCBnZW5kZXIgYW5kIHllYXIuCmBgYHtyIExpZmUgZXhwZWN0YW5jeSBhdCBiaXJ0aH0KCnBsPC0gZGZfZXhwZWN0YW5jeSAlPiUgZmlsdGVyKEFnZSAlaW4lIGMoMCkpICU+JQogIGdncGxvdChtYXBwaW5nID0gYWVzKHg9WWVhciwgeT1yZXNfbGV4LCBjb2xvdXI9YXMuZmFjdG9yKEdlbmRlcikpKSArCiAgZ2d0aXRsZSgiTGlmZSBleHBlY3RhbmN5IGF0IGJpcnRoXG4gYXMgYSBmdW5jdGlvbiBvZiB0aW1lIGJ5IGNvdW50cnkgYW5kIGdlbmRlciIpICsKICBnZW9tX2xpbmUoKSArCiAgZmFjZXRfZ3JpZChDb3VudHJ5fi4pICsKICBsYWJzKGNvbG91cj0iR2VuZGVyIiwgeT0iTGlmZSBleHBlY3RhbmN5IikKYGBgCmBgYHtyIExpZmUgZXhwZWN0YW5jeSBhdCBiaXJ0aCBzYXZlfQpnZ3NhdmUocGwsIGZpbGVuYW1lID0gcGFzdGUocGFyYW1zJHBsb3RwYXRoLCAiZXhwXzAucG5nIiwgc2VwPSIiKSwgZGV2aWNlPU5VTEwsIGhlaWdodCA9IDcgKiAxLjUsIHdpZHRoID0gMyAqIDIuMjUpCmBgYAohW10oUExPVFMvZXhwXzAucG5nKQpIZXJlIHdlIGNhbiBzZWUgdGhhdCB0aGUgdGhlIGxpZmUgZXhwYW5jdGFuY3kgYXQgYmlydGggaGFzIGluY3JlYXNlZCBhIGxvdCB0aGUgcGFzdCAxNTAgeWVhcnMuClRoZXJlIGFyZSB0d28gbG93IHBlYWtzIGR1cmluZyB0aGUgdHdvIHdvcmxkIHdhcnMgZm9yIGV1cm9wZWFuIGNvdW50cmllcywgZXNwZWNpYWxseSBmb3IgbWVuLgpGZW1hbGVzIGhhdmUgaGlnaGVyIGxpZmUgZXhwZWN0YW5jeSB0aGFuIG1hbGVzIGluIGVhY2ggY291bnRyeS4KCmBgYHtyIHJldGlyZW1lbnR9CnBsIDwtIGRmX2V4cGVjdGFuY3kgJT4lCiAgZmlsdGVyKEFnZSAlaW4lIGMoNjAsIDY1KSkgJT4lCiAgZ2dwbG90KG1hcHBpbmcgPSBhZXMoeD1ZZWFyLCB5PXJlc19sZXgsIGNvbG91cj1hcy5mYWN0b3IoQWdlKSkpICsKICBnZ3RpdGxlKCJSZXNpZHVhbCBsaWZlIGV4cGVjdGFuY3kgYXQgNjAgYW5kIDY1IHllYXJzIG9sZHNcbiBhcyBhIGZ1bmN0aW9uIG9mIHRpbWUgYnkgY291bnRyeSBhbmQgZ2VuZGVyIikgKwogIGdlb21fbGluZSgpICsKICBmYWNldF9ncmlkKENvdW50cnkgfiBHZW5kZXIpICsKICBsYWJzKGNvbG91cj0iQWdlIiwgeT0iUmVzaWR1YWwgbGlmZSBleHBlY3RhbmN5IikKYGBgCmBgYHtyIHJldGlyZW1lbnQgc2F2ZX0KZ2dzYXZlKHBsLCBmaWxlbmFtZSA9IHBhc3RlKHBhcmFtcyRwbG90cGF0aCwgImV4cF82MC5wbmciLCBzZXA9IiIpLCBkZXZpY2U9TlVMTCwgaGVpZ2h0ID0gNyAqIDEuNSwgd2lkdGggPSAzICogMi4yNSkKYGBgCgohW10oUExPVFMvZXhwXzYwLnBuZykKCldlIG9ic2VydmUgdGhhdCB0aGUgcmVzaWR1YWwgbGlmZSBleHBlY3RhbmN5IGlzIGluY3JlYXNpbmcgYXMgdGhlIHRpbWUgZ29lcywgYW5kIHRoaXMgcmlzZSBpcyBnb2luZyBmYXN0ZXIgc2luY2UgY2lyY2EgMTk3NS4KV2UgYWxzbyBub3RpY2UgdGhhdCB0aGUgcmVzaWR1YWwgbGlmZSBleHBlY3RhbmN5IG9mIHdvbWVuIGlzIGhpZ2hlciB0aGFuIHRoZSBtZW4ncyBvbmUgZm9yIGVhY2ggY291bnRyeS4KVGhlIFVTIGlzIG9uY2UgYWdhaW4gYSBsaXR0bGUgYmVsbG93IGV1cm9wZWFuIGNvdW50cmllcywgd2l0aCB0aGUgbG93ZXN0IGxpZmUgZXhwZWN0YW5jeSBmb3IgYm90aCBtZW4gYW5kIHdvbWVuLgpJbiBOZXRoZXJsYW5kcyB3ZSBvYnNlcnZlIGEgbGl0dGxlIGRlY3JlYXNpbmcgaW4gdGhlIHJlc2lkdWFsIGxpZmUgZXhwZWN0YW5jeSBiZXR3ZWVuIDE5NTAgYW5kIDE5NzAgYmVmb3JlIGluY3JlYXNpbmcgYWdhaW4uCgojIFBDQQoKYGBge3J9CnN0YW5kYXJkaXplIDwtIGZ1bmN0aW9uKGRmKXsKICBkcGx5cjo6bXV0YXRlX2lmKGRmLCAucHJlZGljYXRlID0gaXMubnVtZXJpYywgLmZ1bnMgPSB+IC4vc2QoLikpCn0KYGBgCgoKYGBge3J9Cm9wcF9sb2cgPC0gZnVuY3Rpb24oeCkge2xvZyh4KX0KZGZfcGl2b3RfbG9nIDwtIGNiaW5kKGRmX3Bpdm90WzE6M10sIGFwcGx5KGRmX3Bpdm90WzQ6MTE0XSwgMiwgb3BwX2xvZykpCmRmX3Bpdm90X2xvZyA8LSBkZl9waXZvdF9sb2cgJT4lZmlsdGVyKFllYXIgJWluJSBjKDE5NDg6MjAxNiksIENvdW50cnkgPT0gcGFyYW1zJGNvdW50cnkpCmRmX3Bpdm90X2xvZy5wY2EgPC0gZGZfcGl2b3RfbG9nICU+JQogIHNlbGVjdCgtYygiWWVhciIsICJHZW5kZXIiLCAiQ291bnRyeSIpKSAlPiUKICBzdGFuZGFyZGl6ZSgpICU+JQogIHByY29tcChzY2FsZS4gPSBUUlVFKQoKZGF0YXRhYmxlKGRmX3Bpdm90X2xvZy5wY2EgJT4lCiAgYnJvb206OnRpZHkobWF0cml4PSJwY3MiKSkKICMlPiUga25pdHI6OmthYmxlKGZvcm1hdD0ibWFya2Rvd24iKQpgYGAKYGBge3IgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KZGF0YXRhYmxlKGRmX3Bpdm90X2xvZyAlPiUKICBkcGx5cjo6c2VsZWN0X2lmKGlzLm51bWVyaWMpICU+JQogIGNvcnJyOjpjb3JyZWxhdGUoKSAlPiUKICBjb3Jycjo6c2hhdmUoKSAlPiUKICBjb3Jycjo6ZmFzaGlvbigpICU+JQogIGtuaXRyOjprYWJsZShmb3JtYXQ9Im1hcmtkb3duIikpCmBgYApgYGB7cn0KIGRmX3N2ZCA8LSBkZl9waXZvdF9sb2cgJT4lCiAgc2VsZWN0KC1jKCJZZWFyIiwgIkdlbmRlciIsICJDb3VudHJ5IikpICU+JQogIHN0YW5kYXJkaXplKCkgJT4lCiAgc3ZkKCkKZGZfc3ZkJGQKYGBgCgoKYGBge3J9CnJvdW5kKCgxMDAqY3Vtc3VtKGRmX3Bpdm90X2xvZy5wY2Ekc2Rldl4yKS9zdW0oZGZfcGl2b3RfbG9nLnBjYSRzZGV2XjIpKSwgMikKYGBgCmBgYHtyfQpkZl9waXZvdF9wY2FfYmlzIDwtIGNiaW5kKGRmX3Bpdm90X2xvZywgZGZfcGl2b3RfbG9nLnBjYSR4KQpgYGAKYGBge3J9CnpwY2EgPC0gZGZfcGl2b3RfbG9nWywgNDoxMTRdICU+JSBwcmNvbXAoKQpxcGxvdCh4ID0xOjExMSwgeT1kZl9waXZvdF9sb2cucGNhJHNkZXZeMiwgZ2VvbT0nY29sJykKYGBgCmBgYHtyfQojZ2diaXBsb3QoZGZfcGl2b3RfcGNhKQpzdW1tYXJ5KGRmX3Bpdm90X2xvZy5wY2EpCiMgZ2diaXBsb3QoZGZfcGl2b3RfbG9nLnBjYSkKZ2diaXBsb3QoZGZfcGl2b3RfbG9nLnBjYSwKICAgICAgICAgI29icy5zY2FsZSA9IDEsCiAgICAgICAgICN2YXIuc2NhbGUgPSAxLAogICAgICAgICBncm91cHMgPSBkZl9waXZvdF9sb2ckR2VuZGVyLAogICAgICAgICBlbGxpcHNlID0gRkFMU0UsCiAgICAgICAgIGNpcmNsZSA9IFRSVUUpICsKICBnZ3RpdGxlKCJCaXBsb3QgYW5kIGNvcnJlbGF0aW9uIGNpcmNsZSIpCmdnYmlwbG90KHpwY2EsCiAgICAgICAgICNvYnMuc2NhbGUgPSAxLAogICAgICAgICAjdmFyLnNjYWxlID0gMSwKICAgICAgICAgZ3JvdXBzID0gZGZfcGl2b3RfbG9nJEdlbmRlciwKICAgICAgICAgZWxsaXBzZSA9IEZBTFNFLAogICAgICAgICBjaXJjbGUgPSBUUlVFKQpgYGAKCmBgYHtyfQpkZl9wY2EgPC0gZGZfcGl2b3RfbG9nICU+JQogIGZpbHRlcihHZW5kZXIgJWluJSBjKCJNYWxlIikpCnJlcy5wY2EgPC0gUENBKGRmX3BjYSAlPiUKICAgICAgICAgICAgICAgICBzZWxlY3QoLWMoIlllYXIiLCAiR2VuZGVyIiwgIkNvdW50cnkiKSkgJT4lCiAgICAgICAgICAgICAgICAgc3RhbmRhcmRpemUoKSwKICAgICAgICAgICAgICAgbmNwID0gMTAsCiAgICAgICAgICAgICAgIGdyYXBoID0gRkFMU0UpCmZ2aXpfZWlnKHJlcy5wY2EsIGFkZGxhYmVscyA9IFRSVUUpCmZ2aXpfcGNhX3ZhcihyZXMucGNhLCBjb2wudmFyID0gImNvbnRyaWIiLCBncmFkaWVudC5jb2xzID0gYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKSkKZnZpel9wY2FfYmlwbG90KHJlcy5wY2EpCiNmdml6X2NvczIocmVzLnBjYSwgY2hvaWNlID0gInZhciIsIGF4ZXMgPSAxOjMpCmZ2aXpfcGNhX2luZChyZXMucGNhLCBjb2wuaW5kID0gZGZfcGNhJFllYXIsCiAgICAgICAgICAgICBncmFkaWVudC5jb2xzID0gYygiYmx1ZSIsICJ5ZWxsb3ciLCAicmVkIiksCiAgICAgICAgICAgICByZXBlbCA9IFRSVUUsICMgQXZvaWQgdGV4dCBvdmVybGFwcGluZyAoc2xvdyBpZiBtYW55IHBvaW50cykKICAgICAgICAgICAgICkKYGBgCk9uIHRoZSBzY3JlZXBsb3Qgd2UgY2FuIHNlZSB0aGF0IHRoZSAzIGZpcnN0IGNvbXBvbmVudCBoYXZlIGFuIGVpZ2VudmFsdWUgPjEgYW5kIGV4cGxhaW5zIGFsbW9zdCA5OCUgb2YgdmFyaWFuY2UsIHRoZXJlZm9yZSB3ZSBjYW4gcmVkdWNlIGRpbWVuc2lvbiBmcm9tIDExNCB0byAzIHdpdGhvdXQgbWFqb3IgbG9zcyBvZiBpbmZvcm1hdGlvbi4KSW4gZmFjdCB0aGUgZmlyc3QgY29tcG9uZW50IGFsb25lIHJlcHJlc2VudCBtb3JlIHRoYW4gODkuNyAlIG9mIHRoZSB2YXJpYW5jZSwgc28gaXQgY291bGQgYmUgYSBnb29kIHVuaXF1ZSBpbmRleCwgYnV0IHdlIHdpbGwgdXNlIEthaXNlcidzIHJ1bGUuCgpPbiB0aGUgY29ycmVsYXRpb24gY2lyY2xlIHdlIGNhbiBzZWUgdGhhdCBhbGwgdGhlIHZhcmlhYmxlcyBhcmUgYmVpbmcgd2VsbCByZXByZXNlbnRlZCwgYW5kIG9uIHRoZSBiaXBsb3QgdGhhdCB0aGVyZSBhcmUgMyBtYWluIGdyb3VwcyBmb3IgYm90aCBzZXguCgoKYGBge3J9CmRmX3Bpdm90X2xvZy5wY2EuYmlzIDwtIGNiaW5kKGRmX3Bpdm90X2xvZywgZGZfcGl2b3RfbG9nLnBjYSR4KSAlPiUgZmlsdGVyKEdlbmRlciAlaW4lIGMoIkZlbWFsZSIsIk1hbGUiLCAiQm90aCIpKQpgYGAKCmBgYHtyfQoKZGZfcGl2b3RfbG9nLnBjYS5iaXMgJT4lCiAgZ2dwbG90KGFlcyh4PVBDMSwgeT1QQzIpKSArCiAgZ2VvbV9wb2ludCgpCgphdXRvcGxvdChkZl9waXZvdF9sb2cucGNhLAogICAgICAgICBkYXRhPWRmX3Bpdm90X2xvZywKICAgICAgICAgY29sb3VyID0gIkdlbmRlciIsCiAgICAgICAgIGxvYWRpbmdzID0gVFJVRSwKICAgICAgICAgbG9hZGluZ3MubGFiZWwgPSBUUlVFLAogICAgICAgICApCmBgYAojIENDQQoKV2UgYnVpbGQgYSBmdW5jdGlvbiBfZGVzaWduXyB0aGF0IHRha2VzIGFzIGlucHV0CiAgKyBhIGRhdGFmcmFtZSBsaWtlIGBsaWZlX3RhYmxlX3Bpdm90YCwKICArIGEgY291cGxlICBvZiBjb3VudHJpZXMsIHNheSBgU3BhaW5gIGFuZCBgU3dlZWRlbmAsCiAgKyBhIHZlY3RvciBvZiBgWWVhcmAsIHNheSBgMTk0ODoxOTk4YAogICsgYSBgR2VuZGVyYCBzYXkgYEZlbWFsZWAKICByZXR1cm5zIGEgbWF0cml4IGNhbGxlZCAkWiQgd2l0aCByb3dzIGNvcnJlc3BvbmRpbmcgdG8gYFllYXJgIGFuZCBjb2x1bW5zCiAgY29ycmVzcG9uZGluZyB0byBjb3VwbGVzIGAoQ291bnRyeSwgQWdlKWAuCgpgYGB7ciBkZXNpZ259CmRlc2lnbiA8LSBmdW5jdGlvbihkZiwgYS5jb3VudHJpZXM9YygiU3BhaW4iLCAiRnJhbmNlIiksIGEueWVhcj0xOTQ4OjE5OTgsIGEuZ2VuZGVyID0gIkZlbWFsZSIpIHsKICBkZl90ZW1wIDwtIGRmICU+JSBmaWx0ZXIoR2VuZGVyPT1hLmdlbmRlciwgQ291bnRyeSAlaW4lIGEuY291bnRyaWVzLCBZZWFyICVpbiUgYS55ZWFyKSAlPiUgc2VsZWN0KC1HZW5kZXIpCiAgZGZfdGVtcCA8LSBkZl90ZW1wICU+JSBwaXZvdF9sb25nZXIoLWMoIlllYXIiLCAiQ291bnRyeSIpLCBuYW1lc190byA9ICJBZ2UiLCB2YWx1ZXNfdG8gPSAibXgiKQogIGRmX3RlbXAgPC0gZGZfdGVtcCAlPiUgcGl2b3Rfd2lkZXIoaWRfY29scyA9ICJZZWFyIiwgbmFtZXNfZnJvbSA9IGMoIkNvdW50cnkiLCAiQWdlIiksIHZhbHVlc19mcm9tPSJteCIpCiAgIyBkYXRhLm1hdHJpeCgKICAjICAgZGZfdGVtcFssIDI6MTEyXQogICMgICAjZGZfdGVtcAogICMgICApCiAgIyBkZl90ZW1wCiAgbSA8LSBkYXRhLm1hdHJpeChkZl90ZW1wKQogIHJvd25hbWVzKG0pIDwtIG1bLDFdCiAgbVssIDI6KGxlbmd0aChhLmNvdW50cmllcykgKiAxMTEgKyAxKV0KfQpgYGAKCgpgYGB7cn0KeiA8LSBkZXNpZ24oZGZfcGl2b3QsIGMoIkZyYW5jZSIpLCBhLmdlbmRlciA9ICJNYWxlIikKcmVzLmNhPC1DQSh6LCBncmFwaCA9IEZBTFNFKQpzdW1tYXJ5KHJlcy5jYSkKZnZpel9jYV9yb3cocmVzLmNhLCByZXBlbCA9IFRSVUUpCmZ2aXpfY2FfY29sKHJlcy5jYSAKICAgICAgICAgICAgIyxyZXBlbCA9IFRSVUUKICAgICAgICAgICAgKQpmdml6X3NjcmVlcGxvdChyZXMuY2EpCmZ2aXpfY2FfYmlwbG90KHJlcy5jYSwgCiAgICAgICAgICAgICAgIG1hcCA9InJvd3ByaW5jaXBhbCIsIGFycm93ID0gYyhUUlVFLCBUUlVFKSwKICAgICAgICAgICAgICAgcmVwZWwgPSBGQUxTRSwgbGFiZWwgPSAibm9uZSIpCmBgYApXZSBzZWUgdGhhdCB0aGUgY2hpLXNxdWFyZSBzdGF0aXN0aWMgaXMgaGlnaCwgd2hpY2ggbWVhbnMgdGhhdCB0aGVyZSBpcyBhIHN0cm9uZyBsaW5rIGJldHdlZW4gdGhlIHllYXIgYW5kIHRoZSBjb3VwbGVzIGAoQ291bnRyeSwgQWdlKWAuCiA5MS45NTYgJSBvZiB0aGUgdmFyaWF0aW9uIGlzIGV4cGxhaW5lZCBieSB0aGUgZmlyc3QgdHdvIGRpbWVuc2lvbnMsIHdoaWNoIGlzIGFjY2VwdGFibGUuCiAKT24gdGhlIGZpcnN0IHBsb3Qgd2UgZGlzdGluZ3Vpc2ggMyBncm91cHMgb2YgeWVhciwgZnJvbSAxOTQ4IHRvIGVhcmx5IDE5NjAsIHRoZSBlbmQgb2YgMTk4MCB0byAxOTk5LCBhbmQgdGhlIGdyb3VwIGZvcm1lZCBieSB0aGUgeWVhcnMgaW4gYmV0d2Vlbi4gCgpPbiB0aGUgc2Vjb25kIHBsb3QsIHdlIHNlZSB0aGF0IGFnZSAwIHRvIDQgYXJlIHJlYWxseSB3ZWxsIHJlcHJlc2VudGVkLgpUaGVuIHdlIGhhdmUgMyBtYWluIGdyb3VwcyBvZiBhZ2UgIDogMCB0byA0MywgNDQgdG8gOTYgYW5kIDk3IHRvIDExMCB3aG8gYXJlIGNvbXBsZXRlbHkgbmVnYXRpdmVseSBjb3JyZWxhdGVkLgoKCiMgTGVlIENhcnRlcgoKUG91ciBmYWlyZSB1bmUgbW9kw6lsaXNhdGlvbiBMZWUtQ2FydGVyIGlsIHN1ZmZpdCBkZSBqb3VlciBhdmVjIGxlcyBwYXJhbcOqdHJlcyBkZSBsYSBmb25jdGlvbiBzdWl2YW50ZToKCiAgICBgbGVlX2NhcnRlciA8LSBmdW5jdGlvbihkZiwgYS5jb3VudHJ5PSJGcmFuY2UiLCBhLnllYXI9MTkzMzoxOTk1LCBhLmdlbmRlciA9ICJCb3RoIilgCgpQb3VyIGFmZmljaGVyIHVuIGdyYXBoIGR1IGZpdDoKCiAgICBgbGVlX2NhcnRlci5maXQgPC0gZnVuY3Rpb24oZGYsIGxlY2EsIHllYXJzID0gTlVMTClgCgpGb3JlY2FzdCBkZXMgJGtfdCQsIGB3YWxrc2AgbGUgbm9tYnJlIGQnYW5uw6llIGRlIHByw6lkaWN0aW9uOgoKICAgIGBsZWNhLmZvcmVjYXN0IDwtIGxlZV9jYXJ0ZXIuZm9yZWNhc3QgPC0gZnVuY3Rpb24obGVjYSwgd2Fsa3MgPSA1MClgCgpQb3VyIGxhIGxpZmUgZXhwZWN0YW5jeSDDoCBwYXJ0aXIgZCd1biBmb3JlY2FzdDoKCiAgICBgbGVjYS5leHBlY3RhbmN5IDwtIGZ1bmN0aW9uKGxlY2EuZm9yZWNhc3QpYAoKUG91ciBjb21wYXJlciBhdmVjIGxlcyB2YWxldXJzIHLDqWVsbGVzLCB2b2lyIGxlIGRlcm5pZXIgZ3JhcGhlLgoKYGBge3J9CmRlc2lnbi51bmlxdWUgPC0gZnVuY3Rpb24oZGYsIGEuY291bnRyeT0iRnJhbmNlIiwgYS55ZWFyPTE5MzM6MTk5NSwgYS5nZW5kZXIgPSAiQm90aCIpIHsKICBkZl90ZW1wIDwtIGRmICU+JSBmaWx0ZXIoR2VuZGVyPT1hLmdlbmRlciwgQ291bnRyeT09YS5jb3VudHJ5LCBZZWFyICVpbiUgYS55ZWFyKSAlPiUgc2VsZWN0KC1jKCJHZW5kZXIiLCAiQ291bnRyeSIpKQogIGRmX3RlbXAgPC0gZGZfdGVtcCAlPiUgcGl2b3RfbG9uZ2VyKC1jKCJZZWFyIiksIG5hbWVzX3RvID0gIkFnZSIsIHZhbHVlc190byA9ICJteCIpCiAgZGZfdGVtcCA8LSBkZl90ZW1wICU+JSBwaXZvdF93aWRlcihpZF9jb2xzID0gIlllYXIiLCBuYW1lc19mcm9tID0iQWdlIiwgdmFsdWVzX2Zyb209Im14IikKICAjIGRhdGEubWF0cml4KAogICMgICBkZl90ZW1wWywgMjoxMTJdCiAgIyAgICNkZl90ZW1wCiAgIyAgICkKICAjIGRmX3RlbXAKICBtIDwtIGRhdGEubWF0cml4KGRmX3RlbXApCiAgcm93bmFtZXMobSkgPC0gbVssMV0KICBtWywgMjoxMTJdCn0KYGBgCgpgYGB7cn0KbGVlX2NhcnRlciA8LSBmdW5jdGlvbihkZiwgYS5jb3VudHJ5PSJGcmFuY2UiLCBhLnllYXI9MTkzMzoxOTk1LCBhLmdlbmRlciA9ICJCb3RoIikgewogIFogPC0gZGVzaWduLnVuaXF1ZShkZiwgYS5jb3VudHJ5LCBhLnllYXIsIGEuZ2VuZGVyKQogICMgYXggPC0gYXMubWF0cml4KGNvbE1lYW5zKFopKQogIFoubG9nIDwtIGFwcGx5KFosIDIsIGxvZykKCiAgIyBUaGUgZmlyc3QgdGhpbmcgd2UgbmVlZCBpcyB0aGUgbWVhbiBsb2ctcmF0ZSBmb3IgZWFjaCBhZ2UgZ3JvdXAuCiAgWi5sb2cuYSA8LSBjb2xNZWFucyhaLmxvZykKICAjIFRoZSBuZXh0IHN0ZXAgaXMgdG8gc3VidHJhY3QgdGhlIGF2ZXJhZ2UgYWdlIHBhdHRlcm4gYSBmcm9tIGFsbCB5ZWFycy4KICBmb3IoaiBpbiAxOihuY29sKFoubG9nKSkpIFoubG9nWyxqXSA8LSBaLmxvZ1ssal0gLSBaLmxvZy5hW2pdCiAgIyBXZSBhcmUgbm93IHJlYWR5IHRvIGNvbXB1dGUgdGhlIFNpbmd1bGFyIFZhbHVlIERlY29tcG9zaXRpb24gKFNWRCkuIFRoZSBmaXJzdCBjb2x1bW4gb2YgVSAgIHRpbWVzIEQxLDEgdGltZXMgdGhlIGZpcnN0IHJvdyBvZiBWJyBoYXMgdGhlIGJlc3QgcmFuay0xIGFwcHJveGltYXRpb24gdG8gdGhlIGlucHV0IG1hdHJpeC4KICBaLmxvZy5zdmQgPC0gc3ZkKFoubG9nLCAxLCAxKQogIFoubG9nLmIgPC0gWi5sb2cuc3ZkJHYgLyBzdW0oWi5sb2cuc3ZkJHYpCiAgWi5sb2cuayA8LSBaLmxvZy5zdmQkdSAqIHN1bShaLmxvZy5zdmQkdikgKiBaLmxvZy5zdmQkZFsxXQoKICBaLmxvZy50cmVuZCA8LSBkYXRhLmZyYW1lKFllYXIgPSBhLnllYXIsIGsgPSBaLmxvZy5rKQogIHN0cnVjdHVyZSgKICAgIGxpc3QoWiA9IFoubG9nLAogICAgICAgICBhID0gWi5sb2cuYSwKICAgICAgICAgYiA9IFoubG9nLmIsCiAgICAgICAgIGsgPSBaLmxvZy5rLAogICAgICAgICB0cmVuZCA9IFoubG9nLnRyZW5kLAogICAgICAgICBzdGFydF95ZWFyID0gaGVhZChhLnllYXIsIG49MSksCiAgICAgICAgIGVuZF95ZWFyID0gdGFpbChhLnllYXIsIG49MSksCiAgICAgICAgIENvdW50cnkgPSBhLmNvdW50cnksCiAgICAgICAgIEdlbmRlciA9IGEuZ2VuZGVyLAogICAgICAgICBBZ2UgPSAwOjExMAogICAgICAgICApCiAgICAsIGNsYXNzPSJsZWVfY2FydGVyIikKfQpgYGAKCmBgYHtyfQpsZWVfY2FydGVyLmZpdCA8LSBmdW5jdGlvbihkZiwgbGVjYSwgYS5zdmQsIHllYXJzID0gTlVMTCkgewogIGlmIChpcy5udWxsKHllYXJzKSkgewogICAgeWVhcnMgPSBjKGxlY2Ekc3RhcnRfeWVhciwgbGVjYSRlbmRfeWVhcikKICB9CgogIGRmX3RlbXAgPC0gZGYgJT4lCiAgICBmaWx0ZXIoR2VuZGVyID09IGxlY2EkR2VuZGVyLCBDb3VudHJ5ID09IGxlY2EkQ291bnRyeSkgJT4lCiAgICBmaWx0ZXIoWWVhciAlaW4lIHllYXJzKSAlPiUKICAgIG11dGF0ZSgKICAgICAgWWVhciA9IGZhY3RvcihZZWFyKSwKICAgICAgZml0ID0gYygKICAgICAgICBzYXBwbHkoeWVhcnMsCiAgICAgICAgICAgICAgIGZ1bmN0aW9uICh4KSB7CiAgICAgICAgICAgICAgICAgZXhwKGxlY2EkYSArIGxlY2EkYiAqIGxlY2Eka1t4IC0gbGVjYSRzdGFydF95ZWFyICsgMV0pCiAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICApKSkKICAKICBkZl90ZW1wIDwtIG1lcmdlKGRmX3RlbXAsIAogICAgICAgICAgICAgICAgICAgYS5zdmQgJT4lIAogICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoWWVhciAlaW4lIHllYXJzKSwgCiAgICAgICAgICAgICAgICAgICBieSA9IGMoIlllYXIiLCAiQWdlIikpCgogIGdncGxvdChkZl90ZW1wLCBhZXMoQWdlLCBjb2xvciA9IFllYXIpKSArCiAgICBnZW9tX2xpbmUoYWVzKHkgPSBteCwgbGluZXR5cGUgPSAiT2JzZXJ2ZWQiKSkgKwogICAgZ2VvbV9saW5lKGFlcyh5ID0gZml0LCBsaW5ldHlwZSA9ICJMZWUtQ2FydGVyIEZpdCIpKSArCiAgICBnZW9tX2xpbmUoYWVzKHkgPSBzdmRfbXgsIGxpbmV0eXBlID0gIlRydW5jYXRlZCByYW5rIDIgU1ZEIEZpdCIpKSArIAogICAgc2NhbGVfeV9sb2cxMCgpICsKICAgIGdndGl0bGUoCiAgICAgIHBhc3RlKCJMZWUtQ2FydGVyIGFuZCB0cnVuY2F0ZWQgcmFuayAyIFNWRCBmaXRzIG9mICIsIGxlY2EkR2VuZGVyLCAKICAgICAgICAgICAgIiBmcm9tICIsIGxlY2EkQ291bnRyeSAsCiAgICAgICAgICAgICJmb3IgeWVhcnMiLCBwYXN0ZSh5ZWFycywgY29sbGFwc2U9IiwgIikKICAgICAgICAgICAgKQogICAgICApICsKICAgIHNjYWxlX2xpbmV0eXBlX21hbnVhbCgibGluZXR5cGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjKCJPYnNlcnZlZCI9MSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJMZWUtQ2FydGVyIEZpdCI9MiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVHJ1bmNhdGVkIHJhbmsgMiBTVkQgRml0IiA9IDMpCiAgICAgICAgICAgICAgICAgICAgICAgICAgKQp9CmBgYAoKCmBgYHtyfQpsZWVfY2FydGVyLmZvcmVjYXN0IDwtIGZ1bmN0aW9uKGxlY2EsIHByZWRpY3QgPSA1MCkgewogIHQgPC0gdHMobGVjYSRrKQogIHJ3IDwtIHJ3Zih0LCBkcmlmdCA9IFRSVUUsIGggPSBwcmVkaWN0KQoKICBvdXQgPSBkYXRhLmZyYW1lKAogICAgWWVhciA9IGludGVnZXIoKSwKICAgIEFnZSA9IGludGVnZXIoKSwKICAgIENvdW50cnkgPSBmYWN0b3IoKSwKICAgIEdlbmRlciA9IGZhY3RvcigpLAogICAgZml0ID0gZG91YmxlKCksCiAgICBsb3cgPSBkb3VibGUoKSwKICAgIGhpID0gZG91YmxlKCkKICApCgogIGZvciAoaSBpbiAxOnByZWRpY3QpIHsKICAgIGZvcmVjYXN0IDwtIGRhdGEuZnJhbWUoCiAgICAgIFllYXIgPSByZXAobGVjYSRlbmRfeWVhciArIGksIGxlbmd0aChsZWNhJEFnZSkpLAogICAgICBDb3VudHJ5ID0gcmVwKGxlY2EkQ291bnRyeSwgbGVuZ3RoKGxlY2EkQWdlKSksCiAgICAgIEdlbmRlciA9IHJlcChsZWNhJEdlbmRlciwgbGVuZ3RoKGxlY2EkQWdlKSksCiAgICAgIEFnZSA9IGxlY2EkQWdlLAogICAgICBmaXQgPSBleHAobGVjYSRhICsgbGVjYSRiICogcnckbWVhbltpXSksCiAgICAgIGxvdyA9IGV4cChsZWNhJGEgKyBsZWNhJGIgKiBydyRsb3dlcltpXSksCiAgICAgIGhpICA9IGV4cChsZWNhJGEgKyBsZWNhJGIgKiBydyR1cHBlcltpXSkKICAgICAgKQogICAgI3ByaW50KGZvcmVjYXN0KQogICAgb3V0IDwtIHJiaW5kKG91dCwgZm9yZWNhc3QpCiAgfQogIG91dAp9CmBgYAoKYGBge3J9CmxlY2EuZXhwZWN0YW5jeSA8LSBmdW5jdGlvbihsZWNhLmZvcmVjYXN0LCB5ZWFycyA9IHNlcSgyMDAwLCAyMDE1LCBieT01KSkgewogIGwgPC0gbGVjYS5mb3JlY2FzdCAlPiUgZmlsdGVyKFllYXIgJWluJSB5ZWFycykKICBnIDwtIGwkR2VuZGVyCiAgYyA8LSBsJENvdW50cnkKICBsIDwtIGwgJT4lIHNlbGVjdChjKCJZZWFyIiwgIkFnZSIsICJmaXQiLCAiaGkiLCAibG93IikpCiAgZiA8LSBsICU+JSBwaXZvdF9sb25nZXIoLWMoIlllYXIiLCAiQWdlIiksIG5hbWVzX3RvID0gIkdlbmRlciIsIHZhbHVlc190byA9ICJteCIpCiAgZiA8LSBsaWZlX2V4cGVjdGFuY3lfYWxsKGYsIGhhcy5jb3VudHJ5ID0gRkFMU0UpCiAgbmFtZXMoZilbbmFtZXMoZikgPT0gIkdlbmRlciJdIDwtICJUeXBlIgogIGYgPC0gZiAlPiUKICBwaXZvdF93aWRlcihpZF9jb2xzID0gYygiWWVhciIsICJBZ2UiKSwgbmFtZXNfZnJvbSA9ICJUeXBlIiwgdmFsdWVzX2Zyb20gPSAicmVzX2xleCIpCiAgZiA8LSBjYmluZChmLCBHZW5kZXI9cmVwKGdbWzFdXSwgbnJvdyhmKSksIENvdW50cnk9cmVwKGNbWzFdXSwgbnJvdyhmKSkpCn0KYGBgCgpgYGB7cn0KbGVjYS5mb3JlY2FzdC5tZXJnZSA8LSBmdW5jdGlvbihsZWNhLmZvcmVjYXN0LCBkZikgewogIG1lcmdlKGxlY2EuZm9yZWNhc3QsIAogICAgICAgIGRmICU+JSBzZWxlY3QoYygiWWVhciIsICJBZ2UiLCAiR2VuZGVyIiwgIkNvdW50cnkiLCAibXgiKSksIAogICAgICAgIGJ5ID0gYygiWWVhciIsICJBZ2UiLCAiR2VuZGVyIiwgIkNvdW50cnkiKSkKfQpsZWNhLmZvcmVjYXN0LmV4cGVjdGFuY3kubWVyZ2UgPC0gZnVuY3Rpb24obGVjYS5mb3JlY2FzdC5leHBlY3RhbmN5LCBkZl9leHBlY3RhbmN5KSB7CiAgbWVyZ2UobGVjYS5mb3JlY2FzdC5leHBlY3RhbmN5LCAKICAgICAgICBkZl9leHBlY3RhbmN5LCAKICAgICAgICBieSA9IGMoIlllYXIiLCAiQWdlIiwgIkdlbmRlciIsICJDb3VudHJ5IikpCn0KYGBgCgpgYGB7cn0KbGVlX2NhcnRlci5hbGwgPC0gZnVuY3Rpb24oZGYsIGEuY291bnRyeT0iRnJhbmNlIiwgYS55ZWFyPTE5MzM6MTk5NSwgYS5nZW5kZXIgPSBjKCJCb3RoIiwgIkZlbWFsZSIsICJNYWxlIikpIHsKICBsID0gbGlzdCgpCiAgZm9yIChnIGluIGEuZ2VuZGVyKSB7CiAgICBsW1tnXV0gPSBsZWVfY2FydGVyKGRmLCBhLmNvdW50cnksIGEueWVhciwgZykKICB9CiAgc3RydWN0dXJlKGxpc3QoZ2VuZGVycyA9IGEuZ2VuZGVyLCBsZWNhID0gbCksIGNsYXNzID0gImxlZV9jYXJ0ZXIuYWxsIikKfQogIApgYGAKCmBgYHtyfQpsZWVfY2FydGVyLmZvcmVjYXN0LmFsbCA8LSBmdW5jdGlvbihsZWNhLmFsbCwgcHJlZGljdCA9IDUwKSB7CiAgb3V0ID0gZGF0YS5mcmFtZSgKICAgIFllYXIgPSBpbnRlZ2VyKCksCiAgICBBZ2UgPSBpbnRlZ2VyKCksCiAgICBDb3VudHJ5ID0gZmFjdG9yKCksCiAgICBHZW5kZXIgPSBmYWN0b3IoKSwKICAgIGZpdCA9IGRvdWJsZSgpLAogICAgbG93ID0gZG91YmxlKCksCiAgICBoaSA9IGRvdWJsZSgpCiAgKQogIAogIGZvciAoZyBpbiBsZWNhLmFsbCRnZW5kZXJzKSB7CiAgICB0IDwtIGxlZV9jYXJ0ZXIuZm9yZWNhc3QobGVjYS5hbGwkbGVjYVtbZ11dLCBwcmVkaWN0KQogICAgb3V0IDwtIHJiaW5kKG91dCwgdCkKICB9CiAgb3V0Cn0KYGBgCgpgYGB7cn0KbGVjYS5mb3JlY2FzdC5wbG90IDwtIGZ1bmN0aW9uKGxlY2EuZm9yZWNhc3QsIGRmLCB5ZWFyID0gMjAxNSwgY291bnRyeSA9ICJGcmFuY2UiKSB7CiAgZyA8LSBsZWNhLmZvcmVjYXN0Lm1lcmdlKGxlY2EuZm9yZWNhc3QsIGRmKSAlPiUKICBmaWx0ZXIoWWVhciAlaW4lIHllYXIsIENvdW50cnkgPT0gY291bnRyeSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gQWdlLCBjb2xvciA9IGFzLmZhY3RvcihHZW5kZXIpKSkgKwogIGdlb21fcmliYm9uKGFlcyh5bWluID0gbG93LCB5bWF4ID0gaGkpLCBmaWxsPSJncmV5IiwgbGluZXR5cGUgPSAiYmxhbmsiKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gZml0LCBsaW5ldHlwZSA9ICJMZWUtQ2FydGVyIEZpdCIpKSArIAogIGdlb21fbGluZShhZXMoeSA9IG14LCBsaW5ldHlwZSA9ICJPYnNlcnZlZCIpKSArCiAgc2NhbGVfeV9sb2cxMCgpCiAgCiAgaWYgKGxlbmd0aCh5ZWFyKSA+IDEpIHsKICAgIGcgPC0gZyArIGZhY2V0X2dyaWQoR2VuZGVyIH4gWWVhcikKICB9IGVsc2UgewogICAgZyA8LSBnICsgZmFjZXRfZ3JpZChHZW5kZXIgfiAuKQogIH0KICAKICBnIDwtIGcgKyBzY2FsZV9saW5ldHlwZV9tYW51YWwoIm14Iix2YWx1ZXM9YygiT2JzZXJ2ZWQiPTIsIkxlZS1DYXJ0ZXIgRml0Ij0xKSkgKwogIGdndGl0bGUocGFzdGUoIkxlZS1DYXJ0ZXIgZm9yZWNhc3QgZm9yIiwgY291bnRyeSwgImZvciIsIHBhc3RlKHllYXIsIGNvbGxhcHNlPSIsICIpLCBzZXAgPSAiICIpKSArIAogIGxhYnMoY29sb3IgPSAiR2VuZGVyIiwgeT0ibG9nIG1vcnRhbGl0eSByYXRlcyIpCiAgZwp9CmBgYAoKYGBge3J9CmxlY2EuZXhwZWN0YW5jeS5hbGwgPC0gZnVuY3Rpb24obGVjYS5mb3JlY2FzdC5hbGwsIHllYXJzID0gc2VxKDIwMDAsIDIwMTUsIGJ5ID0gNSkpIHsKICBnZW5kZXJzID0gYygiQm90aCIsICJGZW1hbGUiLCAiTWFsZSIpCiAgCiAgb3V0IDwtIGRhdGEuZnJhbWUoCiAgICBZZWFyID0gaW50ZWdlcigpLAogICAgQ291bnRyeSA9IGZhY3RvcigpLAogICAgR2VuZGVyID0gZmFjdG9yKCksCiAgICBBZ2UgPSBpbnRlZ2VyKCksCiAgICBmaXQgPSBudW1lcmljKCksCiAgICBsb3cgPSBudW1lcmljKCksCiAgICBoaSA9IG51bWVyaWMoKQogICkKICAKICBmb3IgKGcgaW4gZ2VuZGVycykgewogICAgbCA8LSBsZWNhLmZvcmVjYXN0LmFsbCAlPiUgZmlsdGVyKEdlbmRlciA9PSBnKQogICAgbCA8LSBsZWNhLmV4cGVjdGFuY3kobCwgeWVhcnMpCiAgICBvdXQgPC0gcmJpbmQob3V0LCBsKQogIH0KICBvdXQKfQpgYGAKCmBgYHtyfQpsZWNhLmZvcmVjYXN0LmV4cGVjdGFuY3kucGxvdCA8LSBmdW5jdGlvbihsZWNhLmZvcmVjYXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGZfZXhwZWN0YW5jeSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHllYXIgPSAyMDE1LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY291bnRyeSA9ICJGcmFuY2UiKSB7CiAgZyA8LSBsZWNhLmZvcmVjYXN0LmV4cGVjdGFuY3kubWVyZ2UobGVjYS5mb3JlY2FzdCwgZGZfZXhwZWN0YW5jeSkgJT4lCiAgZmlsdGVyKFllYXIgJWluJSB5ZWFyLCBDb3VudHJ5ID09IGNvdW50cnkpICU+JQogIGdncGxvdChhZXMoeCA9IEFnZSwgY29sb3IgPSBhcy5mYWN0b3IoR2VuZGVyKSkpICsKICBnZW9tX3JpYmJvbihhZXMoeW1pbiA9IGxvdywgeW1heCA9IGhpKSwgZmlsbD0iZ3JleSIsIGxpbmV0eXBlID0gImJsYW5rIikgKwogIGdlb21fbGluZShhZXMoeSA9IGZpdCwgbGluZXR5cGUgPSAiTGVlLUNhcnRlciBGaXQiKSkgKyAKICBnZW9tX2xpbmUoYWVzKHkgPSByZXNfbGV4LCBsaW5ldHlwZSA9ICJPYnNlcnZlZCIpKQogIAogIGlmIChsZW5ndGgoeWVhcikgPiAxKSB7CiAgICBnIDwtIGcgKyBmYWNldF9ncmlkKEdlbmRlciB+IFllYXIpCiAgfSBlbHNlIHsKICAgIGcgPC0gZyArIGZhY2V0X2dyaWQoR2VuZGVyIH4gLikKICB9CiAgCiAgZyA8LSBnICsgc2NhbGVfbGluZXR5cGVfbWFudWFsKCJteCIsdmFsdWVzPWMoIk9ic2VydmVkIj0yLCJMZWUtQ2FydGVyIEZpdCI9MSkpICsKICBnZ3RpdGxlKHBhc3RlKCJMZWUtQ2FydGVyIHJlc2lkdWFsIGxpZmUgZXhwZWN0YW5jeSBmb3JlY2FzdCBmb3IiLCBjb3VudHJ5LCAiZm9yIiwgcGFzdGUoeWVhciwgY29sbGFwc2U9IiwgIiksIHNlcCA9ICIgIikpICsgCiAgbGFicyhjb2xvciA9ICJHZW5kZXIiLCB5PSJSZXNpZHVhbCBsaWZlIGV4cGVjdGFuY3kiKQogIGcKfQpgYGAKCgpgYGB7cn0KeWVhcnMgPSAxOTMzOjE5OTUKY291bnRyeSA9ICJVU0EiCgojdHJ1bmtfc3ZkIDwtIGZ1bmN0aW9uKGRmX3Bpdm90LCBjb3VudHJ5ID0gIkZyYW5jZSIsICB5ZWFycyA9IDE5MzM6MTk5NSkgewoKI1NWRApaLnRzdmQuZiA8LSBzdmRzKHQoZGVzaWduLnVuaXF1ZShkZl9waXZvdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGEuY291bnRyeSA9IGNvdW50cnksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhLnllYXIgPSB5ZWFycywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGEuZ2VuZGVyID0gIkZlbWFsZSIpKSwgCiAgICAgICAgICAgICAgICAgMikKWi50c3ZkLm0gPC0gc3Zkcyh0KGRlc2lnbi51bmlxdWUoZGZfcGl2b3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhLmNvdW50cnkgPSBjb3VudHJ5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYS55ZWFyID0geWVhcnMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhLmdlbmRlciA9ICJNYWxlIikpLCAKICAgICAgICAgICAgICAgICAyKQpaLnRzdmQudCA8LSBzdmRzKHQoZGVzaWduLnVuaXF1ZShkZl9waXZvdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGEuY291bnRyeSA9IGNvdW50cnksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhLnllYXIgPSB5ZWFycywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGEuZ2VuZGVyID0gIkJvdGgiKSksIAogICAgICAgICAgICAgICAgIDIpCgojcmVjb25zdHJ1Y3Rpb24gb2YgdGhlIGVzdGltYXRpb24KWi5yZWNvbi5mIDwtIFoudHN2ZC5mJHUgJSolIGRpYWcoWi50c3ZkLmYkZCkgJSolIHQoWi50c3ZkLmYkdikKCloucmVjb24ubSA8LSBaLnRzdmQubSR1ICUqJSBkaWFnKFoudHN2ZC5tJGQpICUqJSB0KFoudHN2ZC5tJHYpCgpaLnJlY29uLnQgPC0gWi50c3ZkLnQkdSAlKiUgZGlhZyhaLnRzdmQudCRkKSAlKiUgdChaLnRzdmQudCR2KQoKI2NvbnZlcnNpb24gYXMgZGF0YWZyYW1lCloucmVjb24uZiA8LSBjYmluZChjKDA6MTEwKSwgWi5yZWNvbi5mKQpjb2xuYW1lcyhaLnJlY29uLmYpID0gYygiQWdlIiwgeWVhcnMpClouZGYuZjwtYXNfZGF0YV9mcmFtZShaLnJlY29uLmYpClouZGYuZiA8LSBaLmRmLmYgJT4lIHBpdm90X2xvbmdlcigtQWdlLCBuYW1lc190byA9ICJZZWFyIiwgdmFsdWVzX3RvID0gInN2ZF9teCIpClouZGYuZiA8LSBjYmluZChaLmRmLmYsIAogICAgICAgICAgICAgICAgR2VuZGVyID0gcmVwKCJGZW1hbGUiLCBucm93KFouZGYuZikpLCAKICAgICAgICAgICAgICAgIENvdW50cnkgPSByZXAoY291bnRyeSwgbnJvdyhaLmRmLmYpKSkKCloucmVjb24ubSA8LSBjYmluZChjKDA6MTEwKSwgWi5yZWNvbi5tKQpjb2xuYW1lcyhaLnJlY29uLm0pID0gYygiQWdlIiwgeWVhcnMpClouZGYubTwtYXNfZGF0YV9mcmFtZShaLnJlY29uLm0pClouZGYubSA8LSBaLmRmLm0gJT4lIHBpdm90X2xvbmdlcigtQWdlLCBuYW1lc190byA9ICJZZWFyIiwgdmFsdWVzX3RvID0gInN2ZF9teCIpClouZGYubSA8LSBjYmluZChaLmRmLnQsIAogICAgICAgICAgICAgICAgR2VuZGVyID0gcmVwKCJNYWxlIiwgbnJvdyhaLmRmLm0pKSwgCiAgICAgICAgICAgICAgICBDb3VudHJ5ID0gcmVwKGNvdW50cnksIG5yb3coWi5kZi5tKSkpCgpaLnJlY29uLnQgPC0gY2JpbmQoYygwOjExMCksIFoucmVjb24udCkKY29sbmFtZXMoWi5yZWNvbi50KSA9IGMoIkFnZSIsIHllYXJzKQpaLmRmLnQgPC1hc19kYXRhX2ZyYW1lKFoucmVjb24udCkKWi5kZi50IDwtIFouZGYudCAlPiUgcGl2b3RfbG9uZ2VyKC1BZ2UsIG5hbWVzX3RvID0gIlllYXIiLCB2YWx1ZXNfdG8gPSAic3ZkX214IikKWi5kZi50IDwtIGNiaW5kKFouZGYudCwgCiAgICAgICAgICAgICAgICBHZW5kZXIgPSByZXAoIkJvdGgiLCBucm93KFouZGYudCkpLCAKICAgICAgICAgICAgICAgIENvdW50cnkgPSByZXAoY291bnRyeSwgbnJvdyhaLmRmLnQpKSkKCiNaLmRmID0gcmJpbmQoWi5kZi5mLCBaLmRmLnQsIFouZGYubSkKI30KYGBgCgpgYGB7ciBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojbGVjYSA8LSBsZWVfY2FydGVyKGRmX3Bpdm90KQpgYGAKCmBgYHtyfQojbGVlX2NhcnRlci5maXQoZGYsIGxlY2EsIHNlcSgxOTM1LCAxOTk1LCBieT0zMCkpCmBgYAoKYGBge3J9CiNsZWNhJHRyZW5kICU+JQojICBnZ3Bsb3QoYWVzKFllYXIsIGspKSArCiMgIGdlb21fbGluZSgpICsKIyAgZ2d0aXRsZSgiTGVlLUNhcnRlciBrIGZvciAxOTMzLTE5OTUiKQpgYGAKCgpgYGB7cn0KI2xlY2EuZm9yZWNhc3QgPC0gbGVlX2NhcnRlci5mb3JlY2FzdChsZWNhKQpgYGAKCmBgYHtyfQojbGVjYS5mb3JlY2FzdC5leHBlY3RhbmN5IDwtIGxlY2EuZXhwZWN0YW5jeShsZWNhLmZvcmVjYXN0KQpgYGAKCmBgYHtyIHZpc3VlbCBkZXMgZml0fQojbGVjYS5mb3JlY2FzdC5leHBlY3RhbmN5ICU+JQojICBmaWx0ZXIoWWVhciAlaW4lIGMoMjAwMCwgMjAwNSwgMjAxMCwgMjAxNSkpICU+JQojICBnZ3Bsb3QoYWVzKHggPSBBZ2UsIHkgPSBmaXQsIGNvbG9yID0gYXMuZmFjdG9yKFllYXIpKSkgKyBnZW9tX2xpbmUoKQpgYGAKCmBgYHtyfQojbGVjYS5mb3JlY2FzdC5leHBlY3RhbmN5LmJpcyA8LSBtZXJnZShsZWNhLmZvcmVjYXN0LmV4cGVjdGFuY3ksIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZl9leHBlY3RhbmN5LCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSBjKCJZZWFyIiwgIkFnZSIsICJHZW5kZXIiLCAiQ291bnRyeSIpKQojbGVjYS5mb3JlY2FzdC5iaXMgPC0gbWVyZ2UobGVjYS5mb3JlY2FzdCwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICBkZiAlPiUgc2VsZWN0KGMoIlllYXIiLCAiQWdlIiwgIkdlbmRlciIsICJDb3VudHJ5IiwgIm14IikpLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gYygiWWVhciIsICJBZ2UiLCAiR2VuZGVyIiwgIkNvdW50cnkiKSkKYGBgCgpgYGB7ciBjb21wYXJhaXNvbn0KI2xlY2EuZm9yZWNhc3QuZXhwZWN0YW5jeS5iaXMgJT4lCiMgIGZpbHRlcihZZWFyID09IDIwMTUpICU+JQojICBnZ3Bsb3QoYWVzKHggPSBBZ2UsIHkgPSBmaXQpKSArCiMgIGdlb21fcmliYm9uKGFlcyh5bWluID0gbG93LCB5bWF4ID0gaGkpLCBmaWxsPSJncmV5IikgKwojICBnZW9tX2xpbmUoKSArCiMgIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4ID0gQWdlLCB5ID0gcmVzX2xleCkpCmBgYApgYGB7cn0KI2xlY2EuZm9yZWNhc3QuYmlzICU+JQojICBmaWx0ZXIoWWVhciA9PSAyMDE1KSAlPiUKIyAgZ2dwbG90KGFlcyh4ID0gQWdlLCB5ID0gbG9nKGZpdCkpKSArCiMgIGdlb21fcmliYm9uKGFlcyh5bWluID0gbG9nKGxvdyksIHltYXggPSBsb2coaGkpKSwgZmlsbD0iZ3JleSIpICsKIyAgZ2VvbV9saW5lKCkgKwojICBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeCA9IEFnZSwgeSA9IGxvZyhteCkpKQpgYGAKCiMjIFVTCgpgYGB7cn0KbGVjYS5hbGwudXMgPC0gbGVlX2NhcnRlci5hbGwoZGZfcGl2b3QsICJVU0EiKQpgYGAKCmBgYHtyfQpjYmluZChZZWFyID0gbGVjYS5hbGwudXMkbGVjYSRCb3RoJHRyZW5kW1siWWVhciJdXSwKICAgICAgQm90aCA9IGxlY2EuYWxsLnVzJGxlY2EkQm90aCR0cmVuZFtbImsiXV0sIAogICAgICBGZW1hbGUgPSBsZWNhLmFsbC51cyRsZWNhJEZlbWFsZSR0cmVuZFtbImsiXV0sIAogICAgICBNYWxlID0gbGVjYS5hbGwudXMkbGVjYSRNYWxlJHRyZW5kW1siayJdXSkgJT4lCiAgZ2dwbG90KGFlcyhZZWFyKSkgKwogIGdlb21fbGluZShhZXMoeSA9IEJvdGgsIGNvbG9yID0gIkJvdGgiKSkgKwogIGdlb21fbGluZShhZXMoeSA9IEZlbWFsZSwgY29sb3IgPSAiRmVtYWxlIikpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBNYWxlLCBjb2xvciA9ICJNYWxlIikpICsKICBzY2FsZV9jb2xvcl9kaXNjcmV0ZSgiY29sb3IiKSArCiAgZ2d0aXRsZSgiTGVlLUNhcnRlciBrYXBwYSB0cmVuZCBmb3IgVVNBIGZvciB5ZWFycyAxOTMzLTE5OTUiKQpgYGAKCmBgYHtyfQpsZWVfY2FydGVyLmZpdChkZiwgbGVjYS5hbGwudXMkbGVjYSRCb3RoLCBaLmRmLnQsIGMoMTkzMywgMTk4MCkpCmBgYAoKYGBge3J9CmxlY2EuZm9yZWNhc3QuYWxsLnVzIDwtIGxlZV9jYXJ0ZXIuZm9yZWNhc3QuYWxsKGxlY2EuYWxsLnVzKQpgYGAKCmBgYHtyfQpwbCA8LSBsZWNhLmZvcmVjYXN0LnBsb3QobGVjYS5mb3JlY2FzdC5hbGwudXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgZGYsIAogICAgICAgICAgICAgICAgICAgICAgICAgeWVhciA9IGMoMjAwMCwgMjAwNSwgMjAxMCwgMjAxNSksIAogICAgICAgICAgICAgICAgICAgICAgICAgY291bnRyeSA9IlVTQSIpCmdnc2F2ZShwbCwgZmlsZW5hbWUgPSBwYXN0ZShwYXJhbXMkcGxvdHBhdGgsICJmb3JlY2FzdF91cy5wbmciLCBzZXA9IiIpLCBkZXZpY2U9TlVMTCwgaGVpZ2h0ID0gMyAqIDIsIHdpZHRoID0gNSAqIDIpCmBgYAoKIVtdKFBMT1RTL2ZvcmVjYXN0X3VzLnBuZykKCmBgYHtyIGV4cGVjdGFuY3kgdXN9CmxlY2EuZm9yZWNhc3QuZXhwZWN0YW5jeS5hbGwudXMgPC0gbGVjYS5leHBlY3RhbmN5LmFsbChsZWNhLmZvcmVjYXN0LmFsbC51cykKYGBgCgoKYGBge3J9CnBsIDwtIGxlY2EuZm9yZWNhc3QuZXhwZWN0YW5jeS5wbG90KGxlY2EuZm9yZWNhc3QuZXhwZWN0YW5jeS5hbGwudXMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZl9leHBlY3RhbmN5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYygyMDAwLCAyMDA1LCAyMDEwLCAyMDE1KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlVTQSIpCmdnc2F2ZShwbCwgZmlsZW5hbWUgPSBwYXN0ZShwYXJhbXMkcGxvdHBhdGgsICJmb3JlY2FzdF91czIucG5nIiwgc2VwPSIiKSwgZGV2aWNlPU5VTEwsIGhlaWdodCA9IDMgKiAyLCB3aWR0aCA9IDUgKiAyKQpgYGAKCiFbXShQTE9UUy9mb3JlY2FzdF91czIucG5nKQoKCiMjIEV1cm9wZQoKYGBge3J9CnllYXJzID0gMTkzMzoxOTk1CmNvdW50cnkgPSAiRnJhbmNlIgoKI3RydW5rX3N2ZCA8LSBmdW5jdGlvbihkZl9waXZvdCwgY291bnRyeSA9ICJGcmFuY2UiLCAgeWVhcnMgPSAxOTMzOjE5OTUpIHsKCiNTVkQKWi50c3ZkLmYgPC0gc3Zkcyh0KGRlc2lnbi51bmlxdWUoZGZfcGl2b3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhLmNvdW50cnkgPSBjb3VudHJ5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYS55ZWFyID0geWVhcnMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhLmdlbmRlciA9ICJGZW1hbGUiKSksIAogICAgICAgICAgICAgICAgIDIpCloudHN2ZC5tIDwtIHN2ZHModChkZXNpZ24udW5pcXVlKGRmX3Bpdm90LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYS5jb3VudHJ5ID0gY291bnRyeSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGEueWVhciA9IHllYXJzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYS5nZW5kZXIgPSAiTWFsZSIpKSwgCiAgICAgICAgICAgICAgICAgMikKWi50c3ZkLnQgPC0gc3Zkcyh0KGRlc2lnbi51bmlxdWUoZGZfcGl2b3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhLmNvdW50cnkgPSBjb3VudHJ5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYS55ZWFyID0geWVhcnMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhLmdlbmRlciA9ICJCb3RoIikpLCAKICAgICAgICAgICAgICAgICAyKQoKI3JlY29uc3RydWN0aW9uIG9mIHRoZSBlc3RpbWF0aW9uCloucmVjb24uZiA8LSBaLnRzdmQuZiR1ICUqJSBkaWFnKFoudHN2ZC5mJGQpICUqJSB0KFoudHN2ZC5mJHYpCgpaLnJlY29uLm0gPC0gWi50c3ZkLm0kdSAlKiUgZGlhZyhaLnRzdmQubSRkKSAlKiUgdChaLnRzdmQubSR2KQoKWi5yZWNvbi50IDwtIFoudHN2ZC50JHUgJSolIGRpYWcoWi50c3ZkLnQkZCkgJSolIHQoWi50c3ZkLnQkdikKCiNjb252ZXJzaW9uIGFzIGRhdGFmcmFtZQpaLnJlY29uLmYgPC0gY2JpbmQoYygwOjExMCksIFoucmVjb24uZikKY29sbmFtZXMoWi5yZWNvbi5mKSA9IGMoIkFnZSIsIHllYXJzKQpaLmRmLmY8LWFzX2RhdGFfZnJhbWUoWi5yZWNvbi5mKQpaLmRmLmYgPC0gWi5kZi5mICU+JSBwaXZvdF9sb25nZXIoLUFnZSwgbmFtZXNfdG8gPSAiWWVhciIsIHZhbHVlc190byA9ICJzdmRfbXgiKQpaLmRmLmYgPC0gY2JpbmQoWi5kZi5mLCAKICAgICAgICAgICAgICAgIEdlbmRlciA9IHJlcCgiRmVtYWxlIiwgbnJvdyhaLmRmLmYpKSwgCiAgICAgICAgICAgICAgICBDb3VudHJ5ID0gcmVwKGNvdW50cnksIG5yb3coWi5kZi5mKSkpCgpaLnJlY29uLm0gPC0gY2JpbmQoYygwOjExMCksIFoucmVjb24ubSkKY29sbmFtZXMoWi5yZWNvbi5tKSA9IGMoIkFnZSIsIHllYXJzKQpaLmRmLm08LWFzX2RhdGFfZnJhbWUoWi5yZWNvbi5tKQpaLmRmLm0gPC0gWi5kZi5tICU+JSBwaXZvdF9sb25nZXIoLUFnZSwgbmFtZXNfdG8gPSAiWWVhciIsIHZhbHVlc190byA9ICJzdmRfbXgiKQpaLmRmLm0gPC0gY2JpbmQoWi5kZi50LCAKICAgICAgICAgICAgICAgIEdlbmRlciA9IHJlcCgiTWFsZSIsIG5yb3coWi5kZi5tKSksIAogICAgICAgICAgICAgICAgQ291bnRyeSA9IHJlcChjb3VudHJ5LCBucm93KFouZGYubSkpKQoKWi5yZWNvbi50IDwtIGNiaW5kKGMoMDoxMTApLCBaLnJlY29uLnQpCmNvbG5hbWVzKFoucmVjb24udCkgPSBjKCJBZ2UiLCB5ZWFycykKWi5kZi50IDwtYXNfZGF0YV9mcmFtZShaLnJlY29uLnQpClouZGYudCA8LSBaLmRmLnQgJT4lIHBpdm90X2xvbmdlcigtQWdlLCBuYW1lc190byA9ICJZZWFyIiwgdmFsdWVzX3RvID0gInN2ZF9teCIpClouZGYudCA8LSBjYmluZChaLmRmLnQsIAogICAgICAgICAgICAgICAgR2VuZGVyID0gcmVwKCJCb3RoIiwgbnJvdyhaLmRmLnQpKSwgCiAgICAgICAgICAgICAgICBDb3VudHJ5ID0gcmVwKGNvdW50cnksIG5yb3coWi5kZi50KSkpCgojWi5kZiA9IHJiaW5kKFouZGYuZiwgWi5kZi50LCBaLmRmLm0pCiN9CmBgYAoKYGBge3J9CmxlY2EuYWxsIDwtIGxlZV9jYXJ0ZXIuYWxsKGRmX3Bpdm90KQpgYGAKCmBgYHtyfQpjYmluZChZZWFyID0gbGVjYS5hbGwkbGVjYSRCb3RoJHRyZW5kW1siWWVhciJdXSwKICAgICAgQm90aCA9IGxlY2EuYWxsJGxlY2EkQm90aCR0cmVuZFtbImsiXV0sIAogICAgICBGZW1hbGUgPSBsZWNhLmFsbCRsZWNhJEZlbWFsZSR0cmVuZFtbImsiXV0sIAogICAgICBNYWxlID0gbGVjYS5hbGwkbGVjYSRNYWxlJHRyZW5kW1siayJdXSkgJT4lCiAgZ2dwbG90KGFlcyhZZWFyKSkgKwogIGdlb21fbGluZShhZXMoeSA9IEJvdGgsIGNvbG9yID0gIkJvdGgiKSkgKwogIGdlb21fbGluZShhZXMoeSA9IEZlbWFsZSwgY29sb3IgPSAiRmVtYWxlIikpICsKICBnZW9tX2xpbmUoYWVzKHkgPSBNYWxlLCBjb2xvciA9ICJNYWxlIikpICsKICBzY2FsZV9jb2xvcl9kaXNjcmV0ZSgiY29sb3IiKSArCiAgZ2d0aXRsZSgiTGVlLUNhcnRlciBrYXBwYSB0cmVuZCBmb3IgRnJhbmNlIGZvciB5ZWFycyAxOTMzLTE5OTUiKQpgYGAKCmBgYHtyfQpsZWVfY2FydGVyLmZpdChkZiwgbGVjYS5hbGwkbGVjYSRCb3RoLCBaLmRmLnQsIGMoMTkzMywgMTk4MCkpCmBgYAoKYGBge3J9CmxlY2EuZm9yZWNhc3QuYWxsIDwtIGxlZV9jYXJ0ZXIuZm9yZWNhc3QuYWxsKGxlY2EuYWxsKQpgYGAKCmBgYHtyfQpwbCA8LSBsZWNhLmZvcmVjYXN0LnBsb3QobGVjYS5mb3JlY2FzdC5hbGwsIGRmLCBjKDIwMDAsIDIwMDUsIDIwMTAsIDIwMTUpKQpnZ3NhdmUocGwsIGZpbGVuYW1lID0gcGFzdGUocGFyYW1zJHBsb3RwYXRoLCAiZm9yZWNhc3RfZXUucG5nIiwgc2VwPSIiKSwgZGV2aWNlPU5VTEwsIGhlaWdodCA9IDMgKiAyLCB3aWR0aCA9IDUgKiAyKQpgYGAKCiFbXShQTE9UUy9mb3JlY2FzdF9ldS5wbmcpCgoKYGBge3IgZXhwZWN0YW5jeSBldX0KbGVjYS5mb3JlY2FzdC5leHBlY3RhbmN5LmFsbCA8LSBsZWNhLmV4cGVjdGFuY3kuYWxsKGxlY2EuZm9yZWNhc3QuYWxsKQpgYGAKCmBgYHtyfQpwbCA8LSBsZWNhLmZvcmVjYXN0LmV4cGVjdGFuY3kucGxvdChsZWNhLmZvcmVjYXN0LmV4cGVjdGFuY3kuYWxsLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGZfZXhwZWN0YW5jeSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoMjAwMCwgMjAwNSwgMjAxMCwgMjAxNSkpCmdnc2F2ZShwbCwgZmlsZW5hbWUgPSBwYXN0ZShwYXJhbXMkcGxvdHBhdGgsICJmb3JlY2FzdF9ldTIucG5nIiwgc2VwPSIiKSwgZGV2aWNlPU5VTEwsIGhlaWdodCA9IDMgKiAyLCB3aWR0aCA9IDUgKiAyKQpgYGAKIVtdKFBMT1RTL2ZvcmVjYXN0X2V1Mi5wbmcpCgojIFJlZmVyZW5jZXMKCl9fTGlmZSB0YWJsZXMgYW5kIGRlbW9ncmFwaHlfXwoKLSBbSHVtYW4gTW9ydGFsaXR5IERhdGFiYXNlXShodHRwczovL3d3dy5tb3J0YWxpdHkub3JnKQotIFtUYWJsZXMgZGUgbW9ydGFsaXTDqSBmcmFuw6dhaXNlcywgSmFjcXVlcyBWYWxsaW4gZXQgRnJhbmNlIE1lc2zDqV0oaHR0cHM6Ly93d3cubGlmZXRhYmxlLmRlL2RhdGEvRlJBL0ZSQTAwMDAxODA2MTk5N0NZMS5wZGYpCi0gW01vZGVsaW5nIGFuZCBGb3JlY2FzdGluZyBVLlMuIE1vcnRhbGl0eSwgUi5ELkxlZSBhbmQgTC5SLiBDYXJ0ZXIsIEpBU0EgMTk5Ml0KLSBbTGVzIGRpbWVuc2lvbnMgZGUgbGEgbW9ydGFsaXTDqSwgUy4gTGVkZXJtYW5uLCBKZWFuIEJyZWFzLCBQb3B1bGF0aW9uLCAxOTU5XQoKX19HcmFwaGljcyBhbmQgcmVwb3J0aW5nX18KCi0gW0ludGVyYWN0aXZlIHdlYi1iYXNlZCBkYXRhIHZpc3VhbGl6YXRpb24gd2l0aCBSLCBwbG90bHksIGFuZCBzaGlueV0oaHR0cHM6Ly9wbG90bHktci5jb20vaW5kZXguaHRtbCkKLSBbUiBmb3IgRGF0YSBTY2llbmNlXShodHRwczovL3I0ZHMuaGFkLmNvLm56KQotIFtMYXllcmVkIGdyYXBoaWNzXShodHRwOi8vdml0YS5oYWQuY28ubnovcGFwZXJzL2xheWVyZWQtZ3JhbW1hci5wZGYpCi0gW1Bsb3RseV0oaHR0cDovL3Bsb3RseS5jb20vKQoKX19UaWR5dmVyc2VfXwoKLSBbdGlkeXNlbGVjdF0oaHR0cHM6Ly90aWR5c2VsZWN0LnItbGliLm9yZy9hcnRpY2xlcy90aWR5c2VsZWN0Lmh0bWwpCi0gW2RicGx5cl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL2RicGx5ci92aWduZXR0ZXMvZGJwbHlyLmh0bWwpCi0gW2RhdGEudGFibGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9SZGF0YXRhYmxlL2RhdGEudGFibGUpCi0gW0RUXShodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL0RULykKCl9fUENBLCBTVkQsIENDQV9fCgotIFtGYWN0b01pbmVSXShodHRwOi8vZmFjdG9taW5lci5mcmVlLmZyL2luZGV4X2ZyLmh0bWwpCi0gW2FkZTRdKGh0dHA6Ly9wYmlsLnVuaXYtbHlvbjEuZnIvYWRlNC9hY2N1ZWlsLnBocCkKLSBbRmFjdG9JbnZlc3RpZ2F0ZV0oaHR0cDovL2ZhY3RvbWluZXIuZnJlZS5mci9yZXBvcnRpbmcvaW5kZXhfZnIuaHRtbCkKLSBbUENBIGFuZCBUaWR5dmVyc2VdKGh0dHBzOi8vY21kbGluZXRpcHMuY29tLzIwMTkvMDUvaG93LXRvLWRvLXBjYS1pbi10aWR5dmVyc2UtZnJhbWV3b3JrLykKLSBbdGlkeXByY29tcF0oaHR0cHM6Ly9icm9vbS50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS90aWR5LnByY29tcC5odG1sKQo=